sys: don't hold uts_sem while accessing userspace memory
Holding uts_sem as a writer while accessing userspace memory allows a
namespace admin to stall all processes that attempt to take uts_sem.
Instead, move data through stack buffers and don't access userspace memory
while uts_sem is held.
Cc: stable@vger.kernel.org
Fixes: 1da177e4c3
("Linux-2.6.12-rc2")
Signed-off-by: Jann Horn <jannh@google.com>
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
This commit is contained in:

committed by
Eric W. Biederman

parent
5820f140ed
commit
42a0cc3478
@@ -197,23 +197,27 @@ SYSCALL_DEFINE5(rt_sigaction, int, sig,
|
||||
|
||||
SYSCALL_DEFINE2(getdomainname, char __user *, name, int, len)
|
||||
{
|
||||
int nlen, err;
|
||||
|
||||
int nlen, err;
|
||||
char tmp[__NEW_UTS_LEN + 1];
|
||||
|
||||
if (len < 0)
|
||||
return -EINVAL;
|
||||
|
||||
down_read(&uts_sem);
|
||||
|
||||
down_read(&uts_sem);
|
||||
|
||||
nlen = strlen(utsname()->domainname) + 1;
|
||||
err = -EINVAL;
|
||||
if (nlen > len)
|
||||
goto out;
|
||||
goto out_unlock;
|
||||
memcpy(tmp, utsname()->domainname, nlen);
|
||||
|
||||
err = -EFAULT;
|
||||
if (!copy_to_user(name, utsname()->domainname, nlen))
|
||||
err = 0;
|
||||
up_read(&uts_sem);
|
||||
|
||||
out:
|
||||
if (copy_to_user(name, tmp, nlen))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
|
||||
out_unlock:
|
||||
up_read(&uts_sem);
|
||||
return err;
|
||||
}
|
||||
|
@@ -519,23 +519,27 @@ asmlinkage void sparc_breakpoint(struct pt_regs *regs)
|
||||
|
||||
SYSCALL_DEFINE2(getdomainname, char __user *, name, int, len)
|
||||
{
|
||||
int nlen, err;
|
||||
int nlen, err;
|
||||
char tmp[__NEW_UTS_LEN + 1];
|
||||
|
||||
if (len < 0)
|
||||
return -EINVAL;
|
||||
|
||||
down_read(&uts_sem);
|
||||
|
||||
down_read(&uts_sem);
|
||||
|
||||
nlen = strlen(utsname()->domainname) + 1;
|
||||
err = -EINVAL;
|
||||
if (nlen > len)
|
||||
goto out;
|
||||
goto out_unlock;
|
||||
memcpy(tmp, utsname()->domainname, nlen);
|
||||
|
||||
err = -EFAULT;
|
||||
if (!copy_to_user(name, utsname()->domainname, nlen))
|
||||
err = 0;
|
||||
up_read(&uts_sem);
|
||||
|
||||
out:
|
||||
if (copy_to_user(name, tmp, nlen))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
|
||||
out_unlock:
|
||||
up_read(&uts_sem);
|
||||
return err;
|
||||
}
|
||||
|
Reference in New Issue
Block a user