Commit 8783a1ce authored by Tomas Olsson's avatar Tomas Olsson Committed by Linus Torvalds

[PATCH] getgroups16() fix

sys_getgroups16 (or rather groups16_to_user()) returns large gids
truncated.  Needs to be fixed, one way or another.  Don't know why the
other similar casts are still there.
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 406e1707
...@@ -364,6 +364,12 @@ struct group_info { ...@@ -364,6 +364,12 @@ struct group_info {
gid_t *blocks[0]; gid_t *blocks[0];
}; };
/*
* get_group_info() must be called with the owning task locked (via task_lock())
* when task != current. The reason being that the vast majority of callers are
* looking at current->group_info, which can not be changed except by the
* current task. Changing current->group_info requires the task lock, too.
*/
#define get_group_info(group_info) do { \ #define get_group_info(group_info) do { \
atomic_inc(&(group_info)->usage); \ atomic_inc(&(group_info)->usage); \
} while (0) } while (0)
...@@ -930,7 +936,9 @@ static inline int thread_group_empty(task_t *p) ...@@ -930,7 +936,9 @@ static inline int thread_group_empty(task_t *p)
extern void unhash_process(struct task_struct *p); extern void unhash_process(struct task_struct *p);
/* /*
* Protects ->fs, ->files, ->mm, ->ptrace and synchronises with wait4(). * Protects ->fs, ->files, ->mm, ->ptrace, ->group_info and synchronises with
* wait4().
*
* Nests both inside and outside of read_lock(&tasklist_lock). * Nests both inside and outside of read_lock(&tasklist_lock).
* It must not be nested with write_lock_irq(&tasklist_lock), * It must not be nested with write_lock_irq(&tasklist_lock),
* neither inside nor outside. * neither inside nor outside.
......
...@@ -39,7 +39,7 @@ asmlinkage long sys_setregid16(old_gid_t rgid, old_gid_t egid) ...@@ -39,7 +39,7 @@ asmlinkage long sys_setregid16(old_gid_t rgid, old_gid_t egid)
asmlinkage long sys_setgid16(old_gid_t gid) asmlinkage long sys_setgid16(old_gid_t gid)
{ {
return sys_setgid((gid_t)gid); return sys_setgid(low2highgid(gid));
} }
asmlinkage long sys_setreuid16(old_uid_t ruid, old_uid_t euid) asmlinkage long sys_setreuid16(old_uid_t ruid, old_uid_t euid)
...@@ -49,7 +49,7 @@ asmlinkage long sys_setreuid16(old_uid_t ruid, old_uid_t euid) ...@@ -49,7 +49,7 @@ asmlinkage long sys_setreuid16(old_uid_t ruid, old_uid_t euid)
asmlinkage long sys_setuid16(old_uid_t uid) asmlinkage long sys_setuid16(old_uid_t uid)
{ {
return sys_setuid((uid_t)uid); return sys_setuid(low2highuid(uid));
} }
asmlinkage long sys_setresuid16(old_uid_t ruid, old_uid_t euid, old_uid_t suid) asmlinkage long sys_setresuid16(old_uid_t ruid, old_uid_t euid, old_uid_t suid)
...@@ -88,12 +88,12 @@ asmlinkage long sys_getresgid16(old_gid_t __user *rgid, old_gid_t __user *egid, ...@@ -88,12 +88,12 @@ asmlinkage long sys_getresgid16(old_gid_t __user *rgid, old_gid_t __user *egid,
asmlinkage long sys_setfsuid16(old_uid_t uid) asmlinkage long sys_setfsuid16(old_uid_t uid)
{ {
return sys_setfsuid((uid_t)uid); return sys_setfsuid(low2highuid(uid));
} }
asmlinkage long sys_setfsgid16(old_gid_t gid) asmlinkage long sys_setfsgid16(old_gid_t gid)
{ {
return sys_setfsgid((gid_t)gid); return sys_setfsgid(low2highgid(gid));
} }
static int groups16_to_user(old_gid_t __user *grouplist, static int groups16_to_user(old_gid_t __user *grouplist,
...@@ -103,7 +103,7 @@ static int groups16_to_user(old_gid_t __user *grouplist, ...@@ -103,7 +103,7 @@ static int groups16_to_user(old_gid_t __user *grouplist,
old_gid_t group; old_gid_t group;
for (i = 0; i < group_info->ngroups; i++) { for (i = 0; i < group_info->ngroups; i++) {
group = (old_gid_t)GROUP_AT(group_info, i); group = high2lowgid(GROUP_AT(group_info, i));
if (put_user(group, grouplist+i)) if (put_user(group, grouplist+i))
return -EFAULT; return -EFAULT;
} }
...@@ -120,7 +120,7 @@ static int groups16_from_user(struct group_info *group_info, ...@@ -120,7 +120,7 @@ static int groups16_from_user(struct group_info *group_info,
for (i = 0; i < group_info->ngroups; i++) { for (i = 0; i < group_info->ngroups; i++) {
if (get_user(group, grouplist+i)) if (get_user(group, grouplist+i))
return -EFAULT; return -EFAULT;
GROUP_AT(group_info, i) = (gid_t)group; GROUP_AT(group_info, i) = low2highgid(group);
} }
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment