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>
7 #include <linux/syscalls.h>
8 #include <linux/namei.h>
9 #include <linux/mount.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>
17 #ifdef CONFIG_SYSCTL_SYSCALL
19 /* Perform the actual read/write of a sysctl table entry. */
20 static int do_sysctl_strategy(struct ctl_table_root
*root
,
21 struct ctl_table
*table
,
22 void __user
*oldval
, size_t __user
*oldlenp
,
23 void __user
*newval
, size_t newlen
)
31 if (sysctl_perm(root
, table
, op
))
34 if (table
->strategy
) {
35 rc
= table
->strategy(table
, oldval
, oldlenp
, newval
, newlen
);
42 /* If there is no strategy routine, or if the strategy returns
43 * zero, proceed with automatic r/w */
44 if (table
->data
&& table
->maxlen
) {
45 rc
= sysctl_data(table
, oldval
, oldlenp
, newval
, newlen
);
52 static int parse_table(const int *name
, int nlen
,
53 void __user
*oldval
, size_t __user
*oldlenp
,
54 void __user
*newval
, size_t newlen
,
55 struct ctl_table_root
*root
,
56 struct ctl_table
*table
)
63 for ( ; table
->ctl_name
|| table
->procname
; table
++) {
66 if (n
== table
->ctl_name
) {
69 if (sysctl_perm(root
, table
, MAY_EXEC
))
76 error
= do_sysctl_strategy(root
, table
,
85 static ssize_t
binary_sysctl(const int *name
, int nlen
,
86 void __user
*oldval
, size_t __user
*oldlenp
,
87 void __user
*newval
, size_t newlen
)
90 struct ctl_table_header
*head
;
91 ssize_t error
= -ENOTDIR
;
93 for (head
= sysctl_head_next(NULL
); head
;
94 head
= sysctl_head_next(head
)) {
95 error
= parse_table(name
, nlen
, oldval
, oldlenp
,
97 head
->root
, head
->ctl_table
);
98 if (error
!= -ENOTDIR
) {
99 sysctl_head_finish(head
);
106 #else /* CONFIG_SYSCTL_SYSCALL */
108 static ssize_t
binary_sysctl(const int *ctl_name
, int nlen
,
109 void __user
*oldval
, size_t __user
*oldlenp
,
110 void __user
*newval
, size_t newlen
)
115 #endif /* CONFIG_SYSCTL_SYSCALL */
117 static void deprecated_sysctl_warning(const int *name
, int nlen
)
119 static int msg_count
;
122 /* Ignore accesses to kernel.version */
123 if ((nlen
== 2) && (name
[0] == CTL_KERN
) && (name
[1] == KERN_VERSION
))
129 "warning: process `%s' used the deprecated sysctl "
130 "system call with ", current
->comm
);
131 for (i
= 0; i
< nlen
; i
++)
132 printk("%d.", name
[i
]);
138 int do_sysctl(int __user
*args_name
, int nlen
,
139 void __user
*oldval
, size_t __user
*oldlenp
,
140 void __user
*newval
, size_t newlen
)
142 int name
[CTL_MAXNAME
];
146 if (nlen
<= 0 || nlen
>= CTL_MAXNAME
)
148 if (oldval
&& !oldlenp
)
150 if (oldlenp
&& get_user(oldlen
, oldlenp
))
153 /* Read in the sysctl name for simplicity */
154 for (i
= 0; i
< nlen
; i
++)
155 if (get_user(name
[i
], args_name
+ i
))
158 deprecated_sysctl_warning(name
, nlen
);
160 return binary_sysctl(name
, nlen
, oldval
, oldlenp
, newval
, newlen
);
164 SYSCALL_DEFINE1(sysctl
, struct __sysctl_args __user
*, args
)
166 struct __sysctl_args tmp
;
169 if (copy_from_user(&tmp
, args
, sizeof(tmp
)))
173 error
= do_sysctl(tmp
.name
, tmp
.nlen
, tmp
.oldval
, tmp
.oldlenp
,
174 tmp
.newval
, tmp
.newlen
);
181 #include <asm/compat.h>
183 struct compat_sysctl_args
{
186 compat_uptr_t oldval
;
187 compat_uptr_t oldlenp
;
188 compat_uptr_t newval
;
189 compat_size_t newlen
;
190 compat_ulong_t __unused
[4];
193 asmlinkage
long compat_sys_sysctl(struct compat_sysctl_args __user
*args
)
195 struct compat_sysctl_args tmp
;
196 compat_size_t __user
*compat_oldlenp
;
197 size_t __user
*oldlenp
= NULL
;
201 if (copy_from_user(&tmp
, args
, sizeof(tmp
)))
204 compat_oldlenp
= compat_ptr(tmp
.oldlenp
);
205 if (compat_oldlenp
) {
206 oldlenp
= compat_alloc_user_space(sizeof(*compat_oldlenp
));
208 if (get_user(oldlen
, compat_oldlenp
) ||
209 put_user(oldlen
, oldlenp
))
214 result
= do_sysctl(compat_ptr(tmp
.name
), tmp
.nlen
,
215 compat_ptr(tmp
.oldval
), oldlenp
,
216 compat_ptr(tmp
.newval
), tmp
.newlen
);
219 if (oldlenp
&& !result
) {
220 if (get_user(oldlen
, oldlenp
) ||
221 put_user(oldlen
, compat_oldlenp
))
228 #endif /* CONFIG_COMPAT */