ipc_sysctl.c 4.1 KB

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