aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorOleg Nesterov <oleg@redhat.com>2010-06-04 17:14:58 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-06-04 18:21:45 -0400
commit485d527686850d68a0e9006dd9904f19f122485e (patch)
tree8400c646135bb4ce68f137004298e1be7fdbd913 /include
parentd6d03f9158516b50d0d343158e3f33bcff1e4ca5 (diff)
sys_personality: change sys_personality() to accept "unsigned int" instead of u_long
task_struct->pesonality is "unsigned int", but sys_personality() paths use "unsigned long pesonality". This means that every assignment or comparison is not right. In particular, if this argument does not fit into "unsigned int" __set_personality() changes the caller's personality and then sys_personality() returns -EINVAL. Turn this argument into "unsigned int" and avoid overflows. Obviously, this is the user-visible change, we just ignore the upper bits. But this can't break the sane application. There is another thing which can confuse the poorly written applications. User-space thinks that this syscall returns int, not long. This means that the returned value can be negative and look like the error code. But note that libc won't be confused and thus errno won't be set, and with this patch the user-space can never get -1 unless sys_personality() really fails. And, most importantly, the negative RET != -1 is only possible if that app previously called personality(RET). Pointed-out-by: Wenming Zhang <wezhang@redhat.com> Suggested-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Oleg Nesterov <oleg@redhat.com> Cc: "H. Peter Anvin" <hpa@zytor.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'include')
-rw-r--r--include/linux/personality.h2
-rw-r--r--include/linux/syscalls.h2
2 files changed, 2 insertions, 2 deletions
diff --git a/include/linux/personality.h b/include/linux/personality.h
index 126120819a0d..eec3bae164d4 100644
--- a/include/linux/personality.h
+++ b/include/linux/personality.h
@@ -12,7 +12,7 @@ struct pt_regs;
12 12
13extern int register_exec_domain(struct exec_domain *); 13extern int register_exec_domain(struct exec_domain *);
14extern int unregister_exec_domain(struct exec_domain *); 14extern int unregister_exec_domain(struct exec_domain *);
15extern int __set_personality(unsigned long); 15extern int __set_personality(unsigned int);
16 16
17#endif /* __KERNEL__ */ 17#endif /* __KERNEL__ */
18 18
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index a1a86a53bc73..7f614ce274a9 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -289,7 +289,7 @@ asmlinkage long sys_capget(cap_user_header_t header,
289 cap_user_data_t dataptr); 289 cap_user_data_t dataptr);
290asmlinkage long sys_capset(cap_user_header_t header, 290asmlinkage long sys_capset(cap_user_header_t header,
291 const cap_user_data_t data); 291 const cap_user_data_t data);
292asmlinkage long sys_personality(u_long personality); 292asmlinkage long sys_personality(unsigned int personality);
293 293
294asmlinkage long sys_sigpending(old_sigset_t __user *set); 294asmlinkage long sys_sigpending(old_sigset_t __user *set);
295asmlinkage long sys_sigprocmask(int how, old_sigset_t __user *set, 295asmlinkage long sys_sigprocmask(int how, old_sigset_t __user *set,