sysctl_binary.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. #include <linux/stat.h>
  2. #include <linux/sysctl.h>
  3. #include "../fs/xfs/linux-2.6/xfs_sysctl.h"
  4. #include <linux/sunrpc/debug.h>
  5. #include <linux/string.h>
  6. #include <net/ip_vs.h>
  7. #include <linux/syscalls.h>
  8. #include <linux/namei.h>
  9. #include <linux/mount.h>
  10. #include <linux/fs.h>
  11. #include <linux/nsproxy.h>
  12. #include <linux/pid_namespace.h>
  13. #include <linux/file.h>
  14. #include <linux/ctype.h>
  15. #include <linux/smp_lock.h>
  16. static int deprecated_sysctl_warning(struct __sysctl_args *args);
  17. #ifdef CONFIG_SYSCTL_SYSCALL
  18. /* Perform the actual read/write of a sysctl table entry. */
  19. static int do_sysctl_strategy(struct ctl_table_root *root,
  20. struct ctl_table *table,
  21. void __user *oldval, size_t __user *oldlenp,
  22. void __user *newval, size_t newlen)
  23. {
  24. int op = 0, rc;
  25. if (oldval)
  26. op |= MAY_READ;
  27. if (newval)
  28. op |= MAY_WRITE;
  29. if (sysctl_perm(root, table, op))
  30. return -EPERM;
  31. if (table->strategy) {
  32. rc = table->strategy(table, oldval, oldlenp, newval, newlen);
  33. if (rc < 0)
  34. return rc;
  35. if (rc > 0)
  36. return 0;
  37. }
  38. /* If there is no strategy routine, or if the strategy returns
  39. * zero, proceed with automatic r/w */
  40. if (table->data && table->maxlen) {
  41. rc = sysctl_data(table, oldval, oldlenp, newval, newlen);
  42. if (rc < 0)
  43. return rc;
  44. }
  45. return 0;
  46. }
  47. static int parse_table(int __user *name, int nlen,
  48. void __user *oldval, size_t __user *oldlenp,
  49. void __user *newval, size_t newlen,
  50. struct ctl_table_root *root,
  51. struct ctl_table *table)
  52. {
  53. int n;
  54. repeat:
  55. if (!nlen)
  56. return -ENOTDIR;
  57. if (get_user(n, name))
  58. return -EFAULT;
  59. for ( ; table->ctl_name || table->procname; table++) {
  60. if (!table->ctl_name)
  61. continue;
  62. if (n == table->ctl_name) {
  63. int error;
  64. if (table->child) {
  65. if (sysctl_perm(root, table, MAY_EXEC))
  66. return -EPERM;
  67. name++;
  68. nlen--;
  69. table = table->child;
  70. goto repeat;
  71. }
  72. error = do_sysctl_strategy(root, table,
  73. oldval, oldlenp,
  74. newval, newlen);
  75. return error;
  76. }
  77. }
  78. return -ENOTDIR;
  79. }
  80. int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *oldlenp,
  81. void __user *newval, size_t newlen)
  82. {
  83. struct ctl_table_header *head;
  84. int error = -ENOTDIR;
  85. if (nlen <= 0 || nlen >= CTL_MAXNAME)
  86. return -ENOTDIR;
  87. if (oldval) {
  88. int old_len;
  89. if (!oldlenp || get_user(old_len, oldlenp))
  90. return -EFAULT;
  91. }
  92. for (head = sysctl_head_next(NULL); head;
  93. head = sysctl_head_next(head)) {
  94. error = parse_table(name, nlen, oldval, oldlenp,
  95. newval, newlen,
  96. head->root, head->ctl_table);
  97. if (error != -ENOTDIR) {
  98. sysctl_head_finish(head);
  99. break;
  100. }
  101. }
  102. return error;
  103. }
  104. SYSCALL_DEFINE1(sysctl, struct __sysctl_args __user *, args)
  105. {
  106. struct __sysctl_args tmp;
  107. int error;
  108. if (copy_from_user(&tmp, args, sizeof(tmp)))
  109. return -EFAULT;
  110. error = deprecated_sysctl_warning(&tmp);
  111. if (error)
  112. goto out;
  113. lock_kernel();
  114. error = do_sysctl(tmp.name, tmp.nlen, tmp.oldval, tmp.oldlenp,
  115. tmp.newval, tmp.newlen);
  116. unlock_kernel();
  117. out:
  118. return error;
  119. }
  120. #else /* CONFIG_SYSCTL_SYSCALL */
  121. SYSCALL_DEFINE1(sysctl, struct __sysctl_args __user *, args)
  122. {
  123. struct __sysctl_args tmp;
  124. int error;
  125. if (copy_from_user(&tmp, args, sizeof(tmp)))
  126. return -EFAULT;
  127. error = deprecated_sysctl_warning(&tmp);
  128. /* If no error reading the parameters then just -ENOSYS ... */
  129. if (!error)
  130. error = -ENOSYS;
  131. return error;
  132. }
  133. #endif /* CONFIG_SYSCTL_SYSCALL */
  134. static int deprecated_sysctl_warning(struct __sysctl_args *args)
  135. {
  136. static int msg_count;
  137. int name[CTL_MAXNAME];
  138. int i;
  139. /* Check args->nlen. */
  140. if (args->nlen < 0 || args->nlen > CTL_MAXNAME)
  141. return -ENOTDIR;
  142. /* Read in the sysctl name for better debug message logging */
  143. for (i = 0; i < args->nlen; i++)
  144. if (get_user(name[i], args->name + i))
  145. return -EFAULT;
  146. /* Ignore accesses to kernel.version */
  147. if ((args->nlen == 2) && (name[0] == CTL_KERN) && (name[1] == KERN_VERSION))
  148. return 0;
  149. if (msg_count < 5) {
  150. msg_count++;
  151. printk(KERN_INFO
  152. "warning: process `%s' used the deprecated sysctl "
  153. "system call with ", current->comm);
  154. for (i = 0; i < args->nlen; i++)
  155. printk("%d.", name[i]);
  156. printk("\n");
  157. }
  158. return 0;
  159. }