ipc_sysctl.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. /*
  2. * Copyright (C) 2007
  3. *
  4. * Author: Eric Biederman <ebiederm@xmision.com>
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License as
  8. * published by the Free Software Foundation, version 2 of the
  9. * License.
  10. */
  11. #include <linux/module.h>
  12. #include <linux/ipc.h>
  13. #include <linux/nsproxy.h>
  14. #include <linux/sysctl.h>
  15. #include <linux/uaccess.h>
  16. #ifdef CONFIG_IPC_NS
  17. static void *get_ipc(ctl_table *table)
  18. {
  19. char *which = table->data;
  20. struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns;
  21. which = (which - (char *)&init_ipc_ns) + (char *)ipc_ns;
  22. return which;
  23. }
  24. #else
  25. #define get_ipc(T) ((T)->data)
  26. #endif
  27. #ifdef CONFIG_PROC_FS
  28. static int proc_ipc_dointvec(ctl_table *table, int write, struct file *filp,
  29. void __user *buffer, size_t *lenp, loff_t *ppos)
  30. {
  31. struct ctl_table ipc_table;
  32. memcpy(&ipc_table, table, sizeof(ipc_table));
  33. ipc_table.data = get_ipc(table);
  34. return proc_dointvec(&ipc_table, write, filp, buffer, lenp, ppos);
  35. }
  36. static int proc_ipc_doulongvec_minmax(ctl_table *table, int write,
  37. struct file *filp, void __user *buffer, size_t *lenp, loff_t *ppos)
  38. {
  39. struct ctl_table ipc_table;
  40. memcpy(&ipc_table, table, sizeof(ipc_table));
  41. ipc_table.data = get_ipc(table);
  42. return proc_doulongvec_minmax(&ipc_table, write, filp, buffer,
  43. lenp, ppos);
  44. }
  45. #else
  46. #define proc_ipc_doulongvec_minmax NULL
  47. #define proc_ipc_dointvec NULL
  48. #endif
  49. #ifdef CONFIG_SYSCTL_SYSCALL
  50. /* The generic sysctl ipc data routine. */
  51. static int sysctl_ipc_data(ctl_table *table, int __user *name, int nlen,
  52. void __user *oldval, size_t __user *oldlenp,
  53. void __user *newval, size_t newlen)
  54. {
  55. size_t len;
  56. void *data;
  57. /* Get out of I don't have a variable */
  58. if (!table->data || !table->maxlen)
  59. return -ENOTDIR;
  60. data = get_ipc(table);
  61. if (!data)
  62. return -ENOTDIR;
  63. if (oldval && oldlenp) {
  64. if (get_user(len, oldlenp))
  65. return -EFAULT;
  66. if (len) {
  67. if (len > table->maxlen)
  68. len = table->maxlen;
  69. if (copy_to_user(oldval, data, len))
  70. return -EFAULT;
  71. if (put_user(len, oldlenp))
  72. return -EFAULT;
  73. }
  74. }
  75. if (newval && newlen) {
  76. if (newlen > table->maxlen)
  77. newlen = table->maxlen;
  78. if (copy_from_user(data, newval, newlen))
  79. return -EFAULT;
  80. }
  81. return 1;
  82. }
  83. #else
  84. #define sysctl_ipc_data NULL
  85. #endif
  86. static struct ctl_table ipc_kern_table[] = {
  87. {
  88. .ctl_name = KERN_SHMMAX,
  89. .procname = "shmmax",
  90. .data = &init_ipc_ns.shm_ctlmax,
  91. .maxlen = sizeof (init_ipc_ns.shm_ctlmax),
  92. .mode = 0644,
  93. .proc_handler = proc_ipc_doulongvec_minmax,
  94. .strategy = sysctl_ipc_data,
  95. },
  96. {
  97. .ctl_name = KERN_SHMALL,
  98. .procname = "shmall",
  99. .data = &init_ipc_ns.shm_ctlall,
  100. .maxlen = sizeof (init_ipc_ns.shm_ctlall),
  101. .mode = 0644,
  102. .proc_handler = proc_ipc_doulongvec_minmax,
  103. .strategy = sysctl_ipc_data,
  104. },
  105. {
  106. .ctl_name = KERN_SHMMNI,
  107. .procname = "shmmni",
  108. .data = &init_ipc_ns.shm_ctlmni,
  109. .maxlen = sizeof (init_ipc_ns.shm_ctlmni),
  110. .mode = 0644,
  111. .proc_handler = proc_ipc_dointvec,
  112. .strategy = sysctl_ipc_data,
  113. },
  114. {
  115. .ctl_name = KERN_MSGMAX,
  116. .procname = "msgmax",
  117. .data = &init_ipc_ns.msg_ctlmax,
  118. .maxlen = sizeof (init_ipc_ns.msg_ctlmax),
  119. .mode = 0644,
  120. .proc_handler = proc_ipc_dointvec,
  121. .strategy = sysctl_ipc_data,
  122. },
  123. {
  124. .ctl_name = KERN_MSGMNI,
  125. .procname = "msgmni",
  126. .data = &init_ipc_ns.msg_ctlmni,
  127. .maxlen = sizeof (init_ipc_ns.msg_ctlmni),
  128. .mode = 0644,
  129. .proc_handler = proc_ipc_dointvec,
  130. .strategy = sysctl_ipc_data,
  131. },
  132. {
  133. .ctl_name = KERN_MSGMNB,
  134. .procname = "msgmnb",
  135. .data = &init_ipc_ns.msg_ctlmnb,
  136. .maxlen = sizeof (init_ipc_ns.msg_ctlmnb),
  137. .mode = 0644,
  138. .proc_handler = proc_ipc_dointvec,
  139. .strategy = sysctl_ipc_data,
  140. },
  141. {
  142. .ctl_name = KERN_SEM,
  143. .procname = "sem",
  144. .data = &init_ipc_ns.sem_ctls,
  145. .maxlen = 4*sizeof (int),
  146. .mode = 0644,
  147. .proc_handler = proc_ipc_dointvec,
  148. .strategy = sysctl_ipc_data,
  149. },
  150. {}
  151. };
  152. static struct ctl_table ipc_root_table[] = {
  153. {
  154. .ctl_name = CTL_KERN,
  155. .procname = "kernel",
  156. .mode = 0555,
  157. .child = ipc_kern_table,
  158. },
  159. {}
  160. };
  161. static int __init ipc_sysctl_init(void)
  162. {
  163. register_sysctl_table(ipc_root_table);
  164. return 0;
  165. }
  166. __initcall(ipc_sysctl_init);