ipc_sysctl.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  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. #include <linux/ipc_namespace.h>
  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. #ifdef CONFIG_PROC_FS
  25. static int proc_ipc_dointvec(ctl_table *table, int write, struct file *filp,
  26. void __user *buffer, size_t *lenp, loff_t *ppos)
  27. {
  28. struct ctl_table ipc_table;
  29. memcpy(&ipc_table, table, sizeof(ipc_table));
  30. ipc_table.data = get_ipc(table);
  31. return proc_dointvec(&ipc_table, write, filp, buffer, lenp, ppos);
  32. }
  33. static int proc_ipc_doulongvec_minmax(ctl_table *table, int write,
  34. struct file *filp, void __user *buffer, size_t *lenp, loff_t *ppos)
  35. {
  36. struct ctl_table ipc_table;
  37. memcpy(&ipc_table, table, sizeof(ipc_table));
  38. ipc_table.data = get_ipc(table);
  39. return proc_doulongvec_minmax(&ipc_table, write, filp, buffer,
  40. lenp, ppos);
  41. }
  42. #else
  43. #define proc_ipc_doulongvec_minmax NULL
  44. #define proc_ipc_dointvec NULL
  45. #endif
  46. #ifdef CONFIG_SYSCTL_SYSCALL
  47. /* The generic sysctl ipc data routine. */
  48. static int sysctl_ipc_data(ctl_table *table, int __user *name, int nlen,
  49. void __user *oldval, size_t __user *oldlenp,
  50. void __user *newval, size_t newlen)
  51. {
  52. size_t len;
  53. void *data;
  54. /* Get out of I don't have a variable */
  55. if (!table->data || !table->maxlen)
  56. return -ENOTDIR;
  57. data = get_ipc(table);
  58. if (!data)
  59. return -ENOTDIR;
  60. if (oldval && oldlenp) {
  61. if (get_user(len, oldlenp))
  62. return -EFAULT;
  63. if (len) {
  64. if (len > table->maxlen)
  65. len = table->maxlen;
  66. if (copy_to_user(oldval, data, len))
  67. return -EFAULT;
  68. if (put_user(len, oldlenp))
  69. return -EFAULT;
  70. }
  71. }
  72. if (newval && newlen) {
  73. if (newlen > table->maxlen)
  74. newlen = table->maxlen;
  75. if (copy_from_user(data, newval, newlen))
  76. return -EFAULT;
  77. }
  78. return 1;
  79. }
  80. #else
  81. #define sysctl_ipc_data NULL
  82. #endif
  83. static struct ctl_table ipc_kern_table[] = {
  84. {
  85. .ctl_name = KERN_SHMMAX,
  86. .procname = "shmmax",
  87. .data = &init_ipc_ns.shm_ctlmax,
  88. .maxlen = sizeof (init_ipc_ns.shm_ctlmax),
  89. .mode = 0644,
  90. .proc_handler = proc_ipc_doulongvec_minmax,
  91. .strategy = sysctl_ipc_data,
  92. },
  93. {
  94. .ctl_name = KERN_SHMALL,
  95. .procname = "shmall",
  96. .data = &init_ipc_ns.shm_ctlall,
  97. .maxlen = sizeof (init_ipc_ns.shm_ctlall),
  98. .mode = 0644,
  99. .proc_handler = proc_ipc_doulongvec_minmax,
  100. .strategy = sysctl_ipc_data,
  101. },
  102. {
  103. .ctl_name = KERN_SHMMNI,
  104. .procname = "shmmni",
  105. .data = &init_ipc_ns.shm_ctlmni,
  106. .maxlen = sizeof (init_ipc_ns.shm_ctlmni),
  107. .mode = 0644,
  108. .proc_handler = proc_ipc_dointvec,
  109. .strategy = sysctl_ipc_data,
  110. },
  111. {
  112. .ctl_name = KERN_MSGMAX,
  113. .procname = "msgmax",
  114. .data = &init_ipc_ns.msg_ctlmax,
  115. .maxlen = sizeof (init_ipc_ns.msg_ctlmax),
  116. .mode = 0644,
  117. .proc_handler = proc_ipc_dointvec,
  118. .strategy = sysctl_ipc_data,
  119. },
  120. {
  121. .ctl_name = KERN_MSGMNI,
  122. .procname = "msgmni",
  123. .data = &init_ipc_ns.msg_ctlmni,
  124. .maxlen = sizeof (init_ipc_ns.msg_ctlmni),
  125. .mode = 0644,
  126. .proc_handler = proc_ipc_dointvec,
  127. .strategy = sysctl_ipc_data,
  128. },
  129. {
  130. .ctl_name = KERN_MSGMNB,
  131. .procname = "msgmnb",
  132. .data = &init_ipc_ns.msg_ctlmnb,
  133. .maxlen = sizeof (init_ipc_ns.msg_ctlmnb),
  134. .mode = 0644,
  135. .proc_handler = proc_ipc_dointvec,
  136. .strategy = sysctl_ipc_data,
  137. },
  138. {
  139. .ctl_name = KERN_SEM,
  140. .procname = "sem",
  141. .data = &init_ipc_ns.sem_ctls,
  142. .maxlen = 4*sizeof (int),
  143. .mode = 0644,
  144. .proc_handler = proc_ipc_dointvec,
  145. .strategy = sysctl_ipc_data,
  146. },
  147. {}
  148. };
  149. static struct ctl_table ipc_root_table[] = {
  150. {
  151. .ctl_name = CTL_KERN,
  152. .procname = "kernel",
  153. .mode = 0555,
  154. .child = ipc_kern_table,
  155. },
  156. {}
  157. };
  158. static int __init ipc_sysctl_init(void)
  159. {
  160. register_sysctl_table(ipc_root_table);
  161. return 0;
  162. }
  163. __initcall(ipc_sysctl_init);