All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] kernel/sys.c: for setfsgid(), return the current gid when error occurs
@ 2013-08-06  8:00 Chen Gang
  2013-08-06  8:01 ` [PATCH 1/2] kernel/sys.c: " Chen Gang
                   ` (3 more replies)
  0 siblings, 4 replies; 26+ messages in thread
From: Chen Gang @ 2013-08-06  8:00 UTC (permalink / raw)
  To: Kees Cook, Al Viro, Oleg Nesterov, holt; +Cc: Andrew Morton, linux-kernel

They are 2 related patches for setfsgid().

Patch 1 for bug fix: return the current gid when error occurs.
Patch 2 for cleaning code: remove useless variable 'old_fsgid'.

Signed-off-by: Chen Gang <gang.chen@asianux.com>
--
 kernel/sys.c |   15 +++++----------
 1 files changed, 5 insertions(+), 10 deletions(-)

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH 1/2] kernel/sys.c: return the current gid when error occurs
  2013-08-06  8:00 [PATCH 0/2] kernel/sys.c: for setfsgid(), return the current gid when error occurs Chen Gang
@ 2013-08-06  8:01 ` Chen Gang
  2013-08-06 20:21   ` Andy Lutomirski
  2013-08-06  8:02 ` [PATCH 2/2] kernel/sys.c: remove useless variable 'old_fsgid' for setfsgid() Chen Gang
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 26+ messages in thread
From: Chen Gang @ 2013-08-06  8:01 UTC (permalink / raw)
  To: Kees Cook, Al Viro, Oleg Nesterov, holt; +Cc: Andrew Morton, linux-kernel

According to the API definition, when error occurs, need return current
fsgid instead of the previous one.

The related informations ("man setfsgid"):

  RETURN VALUE
         On success, the previous value of fsgid is returned.  On error, the current value of fsgid is returned.

Signed-off-by: Chen Gang <gang.chen@asianux.com>
---
 kernel/sys.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/kernel/sys.c b/kernel/sys.c
index 771129b..9356dc8 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -775,11 +775,11 @@ SYSCALL_DEFINE1(setfsgid, gid_t, gid)
 
 	kgid = make_kgid(old->user_ns, gid);
 	if (!gid_valid(kgid))
-		return old_fsgid;
+		return gid;
 
 	new = prepare_creds();
 	if (!new)
-		return old_fsgid;
+		return gid;
 
 	if (gid_eq(kgid, old->gid)  || gid_eq(kgid, old->egid)  ||
 	    gid_eq(kgid, old->sgid) || gid_eq(kgid, old->fsgid) ||
@@ -791,7 +791,7 @@ SYSCALL_DEFINE1(setfsgid, gid_t, gid)
 	}
 
 	abort_creds(new);
-	return old_fsgid;
+	return gid;
 
 change_okay:
 	commit_creds(new);
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 2/2] kernel/sys.c: remove useless variable 'old_fsgid' for setfsgid()
  2013-08-06  8:00 [PATCH 0/2] kernel/sys.c: for setfsgid(), return the current gid when error occurs Chen Gang
  2013-08-06  8:01 ` [PATCH 1/2] kernel/sys.c: " Chen Gang
@ 2013-08-06  8:02 ` Chen Gang
  2013-08-06  8:56   ` Chen Gang
  2013-08-06  8:13 ` kernel/sys.c: for setfsuid(), return the current uid when error occurs Chen Gang
  2013-08-06 18:36 ` [PATCH 0/2] kernel/sys.c: for setfsgid(), return the current gid when error occurs Kees Cook
  3 siblings, 1 reply; 26+ messages in thread
From: Chen Gang @ 2013-08-06  8:02 UTC (permalink / raw)
  To: Kees Cook, Al Viro, Oleg Nesterov, holt; +Cc: Andrew Morton, linux-kernel

Remove useless variable 'old_fsgid' to make code clearer for readers.

Signed-off-by: Chen Gang <gang.chen@asianux.com>
---
 kernel/sys.c |    9 ++-------
 1 files changed, 2 insertions(+), 7 deletions(-)

diff --git a/kernel/sys.c b/kernel/sys.c
index 9356dc8..fc169d8 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -767,11 +767,9 @@ SYSCALL_DEFINE1(setfsgid, gid_t, gid)
 {
 	const struct cred *old;
 	struct cred *new;
-	gid_t old_fsgid;
 	kgid_t kgid;
 
 	old = current_cred();
-	old_fsgid = from_kgid_munged(old->user_ns, old->fsgid);
 
 	kgid = make_kgid(old->user_ns, gid);
 	if (!gid_valid(kgid))
@@ -786,16 +784,13 @@ SYSCALL_DEFINE1(setfsgid, gid_t, gid)
 	    nsown_capable(CAP_SETGID)) {
 		if (!gid_eq(kgid, old->fsgid)) {
 			new->fsgid = kgid;
-			goto change_okay;
+			commit_creds(new);
+			return from_kgid_munged(old->user_ns, old->fsgid);
 		}
 	}
 
 	abort_creds(new);
 	return gid;
-
-change_okay:
-	commit_creds(new);
-	return old_fsgid;
 }
 
 /**
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* kernel/sys.c: for setfsuid(), return the current uid when error occurs
  2013-08-06  8:00 [PATCH 0/2] kernel/sys.c: for setfsgid(), return the current gid when error occurs Chen Gang
  2013-08-06  8:01 ` [PATCH 1/2] kernel/sys.c: " Chen Gang
  2013-08-06  8:02 ` [PATCH 2/2] kernel/sys.c: remove useless variable 'old_fsgid' for setfsgid() Chen Gang
@ 2013-08-06  8:13 ` Chen Gang
  2013-08-06  8:14   ` Chen Gang
  2013-08-06  8:15   ` [PATCH 0/2] " Chen Gang
  2013-08-06 18:36 ` [PATCH 0/2] kernel/sys.c: for setfsgid(), return the current gid when error occurs Kees Cook
  3 siblings, 2 replies; 26+ messages in thread
From: Chen Gang @ 2013-08-06  8:13 UTC (permalink / raw)
  To: Kees Cook, Al Viro, Oleg Nesterov, holt; +Cc: Andrew Morton, linux-kernel

They are 2 related patches for setfsuid().

Patch 1 for bug fix: return the current uid when error occurs.
Patch 2 for cleaning code: remove useless variable 'old_fsuid'.

Signed-off-by: Chen Gang <gang.chen@asianux.com>
--
 kernel/sys.c |   14 ++++++--------
 1 files changed, 6 insertions(+), 8 deletions(-)

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: kernel/sys.c: for setfsuid(), return the current uid when error occurs
  2013-08-06  8:13 ` kernel/sys.c: for setfsuid(), return the current uid when error occurs Chen Gang
@ 2013-08-06  8:14   ` Chen Gang
  2013-08-06  8:15   ` [PATCH 0/2] " Chen Gang
  1 sibling, 0 replies; 26+ messages in thread
From: Chen Gang @ 2013-08-06  8:14 UTC (permalink / raw)
  To: Kees Cook, Al Viro, Oleg Nesterov, holt; +Cc: Andrew Morton, linux-kernel


Please skip it, sorry for bothering you with waste information.

On 08/06/2013 04:13 PM, Chen Gang wrote:
> They are 2 related patches for setfsuid().
> 
> Patch 1 for bug fix: return the current uid when error occurs.
> Patch 2 for cleaning code: remove useless variable 'old_fsuid'.
> 
> Signed-off-by: Chen Gang <gang.chen@asianux.com>
> --
>  kernel/sys.c |   14 ++++++--------
>  1 files changed, 6 insertions(+), 8 deletions(-)
> 


-- 
Chen Gang

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH 0/2] kernel/sys.c: for setfsuid(), return the current uid when error occurs
  2013-08-06  8:13 ` kernel/sys.c: for setfsuid(), return the current uid when error occurs Chen Gang
  2013-08-06  8:14   ` Chen Gang
@ 2013-08-06  8:15   ` Chen Gang
  2013-08-06  8:15     ` [PATCH 1/2] kernel/sys.c: " Chen Gang
                       ` (2 more replies)
  1 sibling, 3 replies; 26+ messages in thread
From: Chen Gang @ 2013-08-06  8:15 UTC (permalink / raw)
  To: Kees Cook, Al Viro, Oleg Nesterov, holt; +Cc: Andrew Morton, linux-kernel

They are 2 related patches for setfsuid().

Patch 1 for bug fix: return the current uid when error occurs.
Patch 2 for cleaning code: remove useless variable 'old_fsuid'.

Signed-off-by: Chen Gang <gang.chen@asianux.com>
--
 kernel/sys.c |   14 ++++++--------
 1 files changed, 6 insertions(+), 8 deletions(-)


^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH 1/2]  kernel/sys.c: return the current uid when error occurs
  2013-08-06  8:15   ` [PATCH 0/2] " Chen Gang
@ 2013-08-06  8:15     ` Chen Gang
  2013-08-06  8:16     ` [PATCH 2/2] kernel/sys.c: remove useless variable 'old_fsuid' for setfsuid() Chen Gang
  2013-08-06  8:43     ` [PATCH] kernel/sys.c: improve the usage of return value Chen Gang
  2 siblings, 0 replies; 26+ messages in thread
From: Chen Gang @ 2013-08-06  8:15 UTC (permalink / raw)
  To: Kees Cook, Al Viro, Oleg Nesterov, holt; +Cc: Andrew Morton, linux-kernel

According to the API definition, when error occurs, need return current
fsuid instead of the previous one.

The related informations ("man setfsuid"):

  RETURN VALUE
         On success, the previous value of fsuid is returned.  On error, the current value of fsuid is returned.


Signed-off-by: Chen Gang <gang.chen@asianux.com>
---
 kernel/sys.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/kernel/sys.c b/kernel/sys.c
index 771129b..558ccdb 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -736,11 +736,11 @@ SYSCALL_DEFINE1(setfsuid, uid_t, uid)
 
 	kuid = make_kuid(old->user_ns, uid);
 	if (!uid_valid(kuid))
-		return old_fsuid;
+		return uid;
 
 	new = prepare_creds();
 	if (!new)
-		return old_fsuid;
+		return uid;
 
 	if (uid_eq(kuid, old->uid)  || uid_eq(kuid, old->euid)  ||
 	    uid_eq(kuid, old->suid) || uid_eq(kuid, old->fsuid) ||
@@ -753,7 +753,7 @@ SYSCALL_DEFINE1(setfsuid, uid_t, uid)
 	}
 
 	abort_creds(new);
-	return old_fsuid;
+	return uid;
 
 change_okay:
 	commit_creds(new);
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 2/2] kernel/sys.c: remove useless variable 'old_fsuid' for setfsuid()
  2013-08-06  8:15   ` [PATCH 0/2] " Chen Gang
  2013-08-06  8:15     ` [PATCH 1/2] kernel/sys.c: " Chen Gang
@ 2013-08-06  8:16     ` Chen Gang
  2013-08-06  8:55       ` Chen Gang
  2013-08-06  8:43     ` [PATCH] kernel/sys.c: improve the usage of return value Chen Gang
  2 siblings, 1 reply; 26+ messages in thread
From: Chen Gang @ 2013-08-06  8:16 UTC (permalink / raw)
  To: Kees Cook, Al Viro, Oleg Nesterov, holt; +Cc: Andrew Morton, linux-kernel

Remove useless variable 'old_fsuid' to make code clearer for readers.

Signed-off-by: Chen Gang <gang.chen@asianux.com>
---
 kernel/sys.c |   14 ++++++--------
 1 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/kernel/sys.c b/kernel/sys.c
index 558ccdb..e3983b2 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -728,11 +728,9 @@ SYSCALL_DEFINE1(setfsuid, uid_t, uid)
 {
 	const struct cred *old;
 	struct cred *new;
-	uid_t old_fsuid;
 	kuid_t kuid;
 
 	old = current_cred();
-	old_fsuid = from_kuid_munged(old->user_ns, old->fsuid);
 
 	kuid = make_kuid(old->user_ns, uid);
 	if (!uid_valid(kuid))
@@ -747,17 +745,17 @@ SYSCALL_DEFINE1(setfsuid, uid_t, uid)
 	    nsown_capable(CAP_SETUID)) {
 		if (!uid_eq(kuid, old->fsuid)) {
 			new->fsuid = kuid;
-			if (security_task_fix_setuid(new, old, LSM_SETID_FS) == 0)
-				goto change_okay;
+			if (security_task_fix_setuid(new,
+			    old, LSM_SETID_FS) == 0) {
+				commit_creds(new);
+				return from_kuid_munged(old->user_ns,
+							old->fsuid);
+			}
 		}
 	}
 
 	abort_creds(new);
 	return uid;
-
-change_okay:
-	commit_creds(new);
-	return old_fsuid;
 }
 
 /*
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH] kernel/sys.c: improve the usage of return value
  2013-08-06  8:15   ` [PATCH 0/2] " Chen Gang
  2013-08-06  8:15     ` [PATCH 1/2] kernel/sys.c: " Chen Gang
  2013-08-06  8:16     ` [PATCH 2/2] kernel/sys.c: remove useless variable 'old_fsuid' for setfsuid() Chen Gang
@ 2013-08-06  8:43     ` Chen Gang
  2013-08-07 10:44       ` Chen Gang
  2 siblings, 1 reply; 26+ messages in thread
From: Chen Gang @ 2013-08-06  8:43 UTC (permalink / raw)
  To: Kees Cook, Al Viro, Oleg Nesterov, holt; +Cc: Andrew Morton, linux-kernel

Improve the usage of return value, so not only can make code clearer
to readers, but also can improve the performance.

Assign the return error code only when error occurs, so can save some
instructions.

For getcpu(), uname(), newuname(), and override_release(), can remove
the return variable to make code clearer and save some instructions.

Also modify the related code to pass "./scripts/checkpatch.pl" checking.


Signed-off-by: Chen Gang <gang.chen@asianux.com>
---
 kernel/sys.c |  147 +++++++++++++++++++++++++++++++---------------------------
 1 files changed, 79 insertions(+), 68 deletions(-)

diff --git a/kernel/sys.c b/kernel/sys.c
index 771129b..a63a350 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -386,13 +386,14 @@ SYSCALL_DEFINE1(setgid, gid_t, gid)
 		return -ENOMEM;
 	old = current_cred();
 
-	retval = -EPERM;
 	if (nsown_capable(CAP_SETGID))
 		new->gid = new->egid = new->sgid = new->fsgid = kgid;
 	else if (gid_eq(kgid, old->gid) || gid_eq(kgid, old->sgid))
 		new->egid = new->fsgid = kgid;
-	else
+	else {
+		retval = -EPERM;
 		goto error;
+	}
 
 	return commit_creds(new);
 
@@ -533,7 +534,6 @@ SYSCALL_DEFINE1(setuid, uid_t, uid)
 		return -ENOMEM;
 	old = current_cred();
 
-	retval = -EPERM;
 	if (nsown_capable(CAP_SETUID)) {
 		new->suid = new->uid = kuid;
 		if (!uid_eq(kuid, old->uid)) {
@@ -542,6 +542,7 @@ SYSCALL_DEFINE1(setuid, uid_t, uid)
 				goto error;
 		}
 	} else if (!uid_eq(kuid, old->uid) && !uid_eq(kuid, new->suid)) {
+		retval = -EPERM;
 		goto error;
 	}
 
@@ -919,31 +920,35 @@ SYSCALL_DEFINE2(setpgid, pid_t, pid, pid_t, pgid)
 	 */
 	write_lock_irq(&tasklist_lock);
 
-	err = -ESRCH;
 	p = find_task_by_vpid(pid);
-	if (!p)
+	if (!p) {
+		err = -ESRCH;
 		goto out;
+	}
 
-	err = -EINVAL;
-	if (!thread_group_leader(p))
+	if (!thread_group_leader(p)) {
+		err = -EINVAL;
 		goto out;
+	}
 
 	if (same_thread_group(p->real_parent, group_leader)) {
-		err = -EPERM;
-		if (task_session(p) != task_session(group_leader))
+		if (task_session(p) != task_session(group_leader)) {
+			err = -EPERM;
 			goto out;
-		err = -EACCES;
-		if (p->did_exec)
+		}
+		if (p->did_exec) {
+			err = -EACCES;
 			goto out;
-	} else {
+		}
+	} else if (p != group_leader) {
 		err = -ESRCH;
-		if (p != group_leader)
-			goto out;
+		goto out;
 	}
 
-	err = -EPERM;
-	if (p->signal->leader)
+	if (p->signal->leader) {
+		err = -EPERM;
 		goto out;
+	}
 
 	pgrp = task_pid(p);
 	if (pgid != pid) {
@@ -951,8 +956,10 @@ SYSCALL_DEFINE2(setpgid, pid_t, pid, pid_t, pgid)
 
 		pgrp = find_vpid(pgid);
 		g = pid_task(pgrp, PIDTYPE_PGID);
-		if (!g || task_session(g) != task_session(group_leader))
+		if (!g || task_session(g) != task_session(group_leader)) {
+			err = -EPERM;
 			goto out;
+		}
 	}
 
 	err = security_task_setpgid(p, pgid);
@@ -962,7 +969,6 @@ SYSCALL_DEFINE2(setpgid, pid_t, pid, pid_t, pgid)
 	if (task_pgrp(p) != pgrp)
 		change_pid(p, PIDTYPE_PGID, pgrp);
 
-	err = 0;
 out:
 	/* All paths lead to here, thus we are safe. -DaveM */
 	write_unlock_irq(&tasklist_lock);
@@ -980,14 +986,16 @@ SYSCALL_DEFINE1(getpgid, pid_t, pid)
 	if (!pid)
 		grp = task_pgrp(current);
 	else {
-		retval = -ESRCH;
 		p = find_task_by_vpid(pid);
-		if (!p)
+		if (!p) {
+			retval = -ESRCH;
 			goto out;
+		}
 		grp = task_pgrp(p);
-		if (!grp)
+		if (!grp) {
+			retval = -ESRCH;
 			goto out;
-
+		}
 		retval = security_task_getpgid(p);
 		if (retval)
 			goto out;
@@ -1017,14 +1025,16 @@ SYSCALL_DEFINE1(getsid, pid_t, pid)
 	if (!pid)
 		sid = task_session(current);
 	else {
-		retval = -ESRCH;
 		p = find_task_by_vpid(pid);
-		if (!p)
+		if (!p) {
+			retval = -ESRCH;
 			goto out;
+		}
 		sid = task_session(p);
-		if (!sid)
+		if (!sid) {
+			retval = -ESRCH;
 			goto out;
-
+		}
 		retval = security_task_getsid(p);
 		if (retval)
 			goto out;
@@ -1096,8 +1106,6 @@ DECLARE_RWSEM(uts_sem);
  */
 static int override_release(char __user *release, size_t len)
 {
-	int ret = 0;
-
 	if (current->personality & UNAME26) {
 		const char *rest = UTS_RELEASE;
 		char buf[65] = { 0 };
@@ -1115,25 +1123,25 @@ static int override_release(char __user *release, size_t len)
 		v = ((LINUX_VERSION_CODE >> 8) & 0xff) + 40;
 		copy = clamp_t(size_t, len, 1, sizeof(buf));
 		copy = scnprintf(buf, copy, "2.6.%u%s", v, rest);
-		ret = copy_to_user(release, buf, copy + 1);
+		return copy_to_user(release, buf, copy + 1);
 	}
-	return ret;
+	return 0;
 }
 
 SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name)
 {
-	int errno = 0;
-
 	down_read(&uts_sem);
-	if (copy_to_user(name, utsname(), sizeof *name))
-		errno = -EFAULT;
+	if (copy_to_user(name, utsname(), sizeof(*name))) {
+		up_read(&uts_sem);
+		return -EFAULT;
+	}
 	up_read(&uts_sem);
 
-	if (!errno && override_release(name->release, sizeof(name->release)))
-		errno = -EFAULT;
-	if (!errno && override_architecture(name))
-		errno = -EFAULT;
-	return errno;
+	if (override_release(name->release, sizeof(name->release)))
+		return -EFAULT;
+	if (override_architecture(name))
+		return -EFAULT;
+	return 0;
 }
 
 #ifdef __ARCH_WANT_SYS_OLD_UNAME
@@ -1142,21 +1150,21 @@ SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name)
  */
 SYSCALL_DEFINE1(uname, struct old_utsname __user *, name)
 {
-	int error = 0;
-
 	if (!name)
 		return -EFAULT;
 
 	down_read(&uts_sem);
-	if (copy_to_user(name, utsname(), sizeof(*name)))
-		error = -EFAULT;
+	if (copy_to_user(name, utsname(), sizeof(*name))) {
+		up_read(&uts_sem);
+		return -EFAULT;
+	}
 	up_read(&uts_sem);
 
-	if (!error && override_release(name->release, sizeof(name->release)))
-		error = -EFAULT;
-	if (!error && override_architecture(name))
-		error = -EFAULT;
-	return error;
+	if (override_release(name->release, sizeof(name->release)))
+		return -EFAULT;
+	if (override_architecture(name))
+		return -EFAULT;
+	return 0;
 }
 
 SYSCALL_DEFINE1(olduname, struct oldold_utsname __user *, name)
@@ -1185,12 +1193,14 @@ SYSCALL_DEFINE1(olduname, struct oldold_utsname __user *, name)
 				__OLD_UTS_LEN);
 	error |= __put_user(0, name->machine + __OLD_UTS_LEN);
 	up_read(&uts_sem);
+	if (error)
+		return -EFAULT;
 
-	if (!error && override_architecture(name))
-		error = -EFAULT;
-	if (!error && override_release(name->release, sizeof(name->release)))
-		error = -EFAULT;
-	return error ? -EFAULT : 0;
+	if (override_architecture(name))
+		return -EFAULT;
+	if (override_release(name->release, sizeof(name->release)))
+		return -EFAULT;
+	return 0;
 }
 #endif
 
@@ -1648,10 +1658,11 @@ static int prctl_set_mm_exe_file(struct mm_struct *mm, unsigned int fd)
 	 * sure that this one is executable as well, to avoid breaking an
 	 * overall picture.
 	 */
-	err = -EACCES;
-	if (!S_ISREG(inode->i_mode)	||
-	    exe.file->f_path.mnt->mnt_flags & MNT_NOEXEC)
+	if (!S_ISREG(inode->i_mode) ||
+	    exe.file->f_path.mnt->mnt_flags & MNT_NOEXEC) {
+		err = -EACCES;
 		goto exit;
+	}
 
 	err = inode_permission(inode, MAY_EXEC);
 	if (err)
@@ -1662,15 +1673,16 @@ static int prctl_set_mm_exe_file(struct mm_struct *mm, unsigned int fd)
 	/*
 	 * Forbid mm->exe_file change if old file still mapped.
 	 */
-	err = -EBUSY;
 	if (mm->exe_file) {
 		struct vm_area_struct *vma;
 
 		for (vma = mm->mmap; vma; vma = vma->vm_next)
 			if (vma->vm_file &&
 			    path_equal(&vma->vm_file->f_path,
-				       &mm->exe_file->f_path))
+				       &mm->exe_file->f_path)) {
+				err = -EBUSY;
 				goto exit_unlock;
+			}
 	}
 
 	/*
@@ -1679,11 +1691,10 @@ static int prctl_set_mm_exe_file(struct mm_struct *mm, unsigned int fd)
 	 * could make a snapshot over all processes running and monitor
 	 * /proc/pid/exe changes to notice unusual activity if needed.
 	 */
-	err = -EPERM;
-	if (test_and_set_bit(MMF_EXE_FILE_CHANGED, &mm->flags))
+	if (test_and_set_bit(MMF_EXE_FILE_CHANGED, &mm->flags)) {
+		err = -EPERM;
 		goto exit_unlock;
-
-	err = 0;
+	}
 	set_mm_exe_file(mm, exe.file);	/* this grabs a reference to exe.file */
 exit_unlock:
 	up_write(&mm->mmap_sem);
@@ -2009,13 +2020,13 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
 SYSCALL_DEFINE3(getcpu, unsigned __user *, cpup, unsigned __user *, nodep,
 		struct getcpu_cache __user *, unused)
 {
-	int err = 0;
 	int cpu = raw_smp_processor_id();
-	if (cpup)
-		err |= put_user(cpu, cpup);
-	if (nodep)
-		err |= put_user(cpu_to_node(cpu), nodep);
-	return err ? -EFAULT : 0;
+
+	if (cpup && put_user(cpu, cpup))
+		return -EFAULT;
+	if (nodep && put_user(cpu_to_node(cpu), nodep))
+		return -EFAULT;
+	return 0;
 }
 
 /**
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: [PATCH 2/2] kernel/sys.c: remove useless variable 'old_fsuid' for setfsuid()
  2013-08-06  8:16     ` [PATCH 2/2] kernel/sys.c: remove useless variable 'old_fsuid' for setfsuid() Chen Gang
@ 2013-08-06  8:55       ` Chen Gang
  0 siblings, 0 replies; 26+ messages in thread
From: Chen Gang @ 2013-08-06  8:55 UTC (permalink / raw)
  To: Kees Cook, Al Viro, Oleg Nesterov, holt; +Cc: Andrew Morton, linux-kernel

On 08/06/2013 04:16 PM, Chen Gang wrote:
> Remove useless variable 'old_fsuid' to make code clearer for readers.
> 
> Signed-off-by: Chen Gang <gang.chen@asianux.com>
> ---
>  kernel/sys.c |   14 ++++++--------
>  1 files changed, 6 insertions(+), 8 deletions(-)
> 
> diff --git a/kernel/sys.c b/kernel/sys.c
> index 558ccdb..e3983b2 100644
> --- a/kernel/sys.c
> +++ b/kernel/sys.c
> @@ -728,11 +728,9 @@ SYSCALL_DEFINE1(setfsuid, uid_t, uid)
>  {
>  	const struct cred *old;
>  	struct cred *new;
> -	uid_t old_fsuid;
>  	kuid_t kuid;
>  
>  	old = current_cred();
> -	old_fsuid = from_kuid_munged(old->user_ns, old->fsuid);
>  

Oh... should old_fsuid be get before commit_creds() or prepare_creds() ?

>  	kuid = make_kuid(old->user_ns, uid);
>  	if (!uid_valid(kuid))
> @@ -747,17 +745,17 @@ SYSCALL_DEFINE1(setfsuid, uid_t, uid)
>  	    nsown_capable(CAP_SETUID)) {
>  		if (!uid_eq(kuid, old->fsuid)) {
>  			new->fsuid = kuid;
> -			if (security_task_fix_setuid(new, old, LSM_SETID_FS) == 0)
> -				goto change_okay;
> +			if (security_task_fix_setuid(new,
> +			    old, LSM_SETID_FS) == 0) {
> +				commit_creds(new);
> +				return from_kuid_munged(old->user_ns,
> +							old->fsuid);
> +			}

Oh... should old_fsuid be get before commit_creds() or prepare_creds() ?

>  		}
>  	}
>  
>  	abort_creds(new);
>  	return uid;
> -
> -change_okay:
> -	commit_creds(new);
> -	return old_fsuid;
>  }
>  
>  /*
> 


-- 
Chen Gang

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 2/2] kernel/sys.c: remove useless variable 'old_fsgid' for setfsgid()
  2013-08-06  8:02 ` [PATCH 2/2] kernel/sys.c: remove useless variable 'old_fsgid' for setfsgid() Chen Gang
@ 2013-08-06  8:56   ` Chen Gang
  0 siblings, 0 replies; 26+ messages in thread
From: Chen Gang @ 2013-08-06  8:56 UTC (permalink / raw)
  To: Kees Cook, Al Viro, Oleg Nesterov, holt; +Cc: Andrew Morton, linux-kernel

On 08/06/2013 04:02 PM, Chen Gang wrote:
> Remove useless variable 'old_fsgid' to make code clearer for readers.
> 
> Signed-off-by: Chen Gang <gang.chen@asianux.com>
> ---
>  kernel/sys.c |    9 ++-------
>  1 files changed, 2 insertions(+), 7 deletions(-)
> 
> diff --git a/kernel/sys.c b/kernel/sys.c
> index 9356dc8..fc169d8 100644
> --- a/kernel/sys.c
> +++ b/kernel/sys.c
> @@ -767,11 +767,9 @@ SYSCALL_DEFINE1(setfsgid, gid_t, gid)
>  {
>  	const struct cred *old;
>  	struct cred *new;
> -	gid_t old_fsgid;
>  	kgid_t kgid;
>  
>  	old = current_cred();
> -	old_fsgid = from_kgid_munged(old->user_ns, old->fsgid);
>  
>  	kgid = make_kgid(old->user_ns, gid);
>  	if (!gid_valid(kgid))
> @@ -786,16 +784,13 @@ SYSCALL_DEFINE1(setfsgid, gid_t, gid)
>  	    nsown_capable(CAP_SETGID)) {
>  		if (!gid_eq(kgid, old->fsgid)) {
>  			new->fsgid = kgid;
> -			goto change_okay;
> +			commit_creds(new);
> +			return from_kgid_munged(old->user_ns, old->fsgid);

The same, should old_fsgid be get before commit_creds() or prepare_creds() ?

Thanks.

>  		}
>  	}
>  
>  	abort_creds(new);
>  	return gid;
> -
> -change_okay:
> -	commit_creds(new);
> -	return old_fsgid;
>  }
>  
>  /**
> 


-- 
Chen Gang

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 0/2] kernel/sys.c: for setfsgid(), return the current gid when error occurs
  2013-08-06  8:00 [PATCH 0/2] kernel/sys.c: for setfsgid(), return the current gid when error occurs Chen Gang
                   ` (2 preceding siblings ...)
  2013-08-06  8:13 ` kernel/sys.c: for setfsuid(), return the current uid when error occurs Chen Gang
@ 2013-08-06 18:36 ` Kees Cook
  2013-08-07  2:25   ` Chen Gang
  3 siblings, 1 reply; 26+ messages in thread
From: Kees Cook @ 2013-08-06 18:36 UTC (permalink / raw)
  To: Chen Gang; +Cc: Al Viro, Oleg Nesterov, Robin Holt, Andrew Morton, linux-kernel

On Tue, Aug 6, 2013 at 1:00 AM, Chen Gang <gang.chen@asianux.com> wrote:
> They are 2 related patches for setfsgid().
>
> Patch 1 for bug fix: return the current gid when error occurs.
> Patch 2 for cleaning code: remove useless variable 'old_fsgid'.
>
> Signed-off-by: Chen Gang <gang.chen@asianux.com>
> --
>  kernel/sys.c |   15 +++++----------
>  1 files changed, 5 insertions(+), 10 deletions(-)

Making a change like this might have dramatic effects. So, a few
questions, to help better understand:

How long as the behavior been this way on Linux?
What is the origin of the documentation that states it differently?
Do existing userspace tools already depend on the current behavior?
What specific problem will be solved by changing this?

Thanks,

-Kees

-- 
Kees Cook
Chrome OS Security

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 1/2] kernel/sys.c: return the current gid when error occurs
  2013-08-06  8:01 ` [PATCH 1/2] kernel/sys.c: " Chen Gang
@ 2013-08-06 20:21   ` Andy Lutomirski
  2013-08-07  3:30     ` Chen Gang
  2013-08-07 16:21     ` Oleg Nesterov
  0 siblings, 2 replies; 26+ messages in thread
From: Andy Lutomirski @ 2013-08-06 20:21 UTC (permalink / raw)
  To: Chen Gang
  Cc: Kees Cook, Al Viro, Oleg Nesterov, holt, Andrew Morton, linux-kernel

On 08/06/2013 01:01 AM, Chen Gang wrote:
> According to the API definition, when error occurs, need return current
> fsgid instead of the previous one.
> 
> The related informations ("man setfsgid"):
> 
>   RETURN VALUE
>          On success, the previous value of fsgid is returned.  On error, the current value of fsgid is returned.
> 
> Signed-off-by: Chen Gang <gang.chen@asianux.com>
> ---
>  kernel/sys.c |    6 +++---
>  1 files changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/kernel/sys.c b/kernel/sys.c
> index 771129b..9356dc8 100644
> --- a/kernel/sys.c
> +++ b/kernel/sys.c
> @@ -775,11 +775,11 @@ SYSCALL_DEFINE1(setfsgid, gid_t, gid)
>  
>  	kgid = make_kgid(old->user_ns, gid);
>  	if (!gid_valid(kgid))
> -		return old_fsgid;
> +		return gid;

Huh?  So if 1234567 is not a valid gid, then setfsgid(1234567) is
supposed to return 1234567?  This makes no sense.

I assume that what the man page means is that the return value is
whatever fsgid was prior to the call.  On error, fsgid isn't changed, so
the return value is still "current".

(FWIW, this behavior is awful and is probably the cause of a security
bug or three, since success and failure are indistinguishable.  But I
think your patch is wrong.)

--Andy

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 0/2] kernel/sys.c: for setfsgid(), return the current gid when error occurs
  2013-08-06 18:36 ` [PATCH 0/2] kernel/sys.c: for setfsgid(), return the current gid when error occurs Kees Cook
@ 2013-08-07  2:25   ` Chen Gang
  0 siblings, 0 replies; 26+ messages in thread
From: Chen Gang @ 2013-08-07  2:25 UTC (permalink / raw)
  To: Kees Cook; +Cc: Al Viro, Oleg Nesterov, Robin Holt, Andrew Morton, linux-kernel

On 08/07/2013 02:36 AM, Kees Cook wrote:
> On Tue, Aug 6, 2013 at 1:00 AM, Chen Gang <gang.chen@asianux.com> wrote:
>> They are 2 related patches for setfsgid().
>>
>> Patch 1 for bug fix: return the current gid when error occurs.
>> Patch 2 for cleaning code: remove useless variable 'old_fsgid'.
>>
>> Signed-off-by: Chen Gang <gang.chen@asianux.com>
>> --
>>  kernel/sys.c |   15 +++++----------
>>  1 files changed, 5 insertions(+), 10 deletions(-)
> 
> Making a change like this might have dramatic effects. So, a few
> questions, to help better understand:
> 
> How long as the behavior been this way on Linux?
> What is the origin of the documentation that states it differently?
> Do existing userspace tools already depend on the current behavior?
> What specific problem will be solved by changing this?
> 

Firstly, your questions are necessary and valuable to get reply.

But sorry, I only find it by reading code, and not quite familiar with
the details (e.g. how to use it, and its history ...).

I only know the original implementation has a kernel API related issue
(at least now, it is), and try to send a possible fixing patch to
mailing list for getting more discussion and better fixing.

So, welcome any members to help reply your valuable questions (and I
should also try to answer them, but at least, I really needs time to
familiar about it).


> Thanks,
> 
> -Kees
> 

Thanks.
-- 
Chen Gang

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 1/2] kernel/sys.c: return the current gid when error occurs
  2013-08-06 20:21   ` Andy Lutomirski
@ 2013-08-07  3:30     ` Chen Gang
  2013-08-07 16:21     ` Oleg Nesterov
  1 sibling, 0 replies; 26+ messages in thread
From: Chen Gang @ 2013-08-07  3:30 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Kees Cook, Al Viro, Oleg Nesterov, holt, Andrew Morton, linux-kernel

On 08/07/2013 04:21 AM, Andy Lutomirski wrote:
> On 08/06/2013 01:01 AM, Chen Gang wrote:
>> According to the API definition, when error occurs, need return current
>> fsgid instead of the previous one.
>>
>> The related informations ("man setfsgid"):
>>
>>   RETURN VALUE
>>          On success, the previous value of fsgid is returned.  On error, the current value of fsgid is returned.
>>
>> Signed-off-by: Chen Gang <gang.chen@asianux.com>
>> ---
>>  kernel/sys.c |    6 +++---
>>  1 files changed, 3 insertions(+), 3 deletions(-)
>>
>> diff --git a/kernel/sys.c b/kernel/sys.c
>> index 771129b..9356dc8 100644
>> --- a/kernel/sys.c
>> +++ b/kernel/sys.c
>> @@ -775,11 +775,11 @@ SYSCALL_DEFINE1(setfsgid, gid_t, gid)
>>  
>>  	kgid = make_kgid(old->user_ns, gid);
>>  	if (!gid_valid(kgid))
>> -		return old_fsgid;
>> +		return gid;
> 
> Huh?  So if 1234567 is not a valid gid, then setfsgid(1234567) is
> supposed to return 1234567?  This makes no sense.
>

Hmm... one explanation is "current value" means the value which will be
set, it may be incorrect, if so, need return with failure (at least, it
is not conflict with the meaning of "current value").

For using:

  Assume the caller's new fsgid is different with the previous one (or the caller need/should not call it).
  If the return value is not equal to the new fsgid, that means the system call succeeds (it is the previous one which may be useful for caller, too).
  If the return value is equal to the new fsgid (the new fsgid may '1234567'), that means the system call fails.

So at least, "man page" description is correct.

 
> I assume that what the man page means is that the return value is
> whatever fsgid was prior to the call.  On error, fsgid isn't changed, so
> the return value is still "current".
> 

Hmm... which 'variable' can be qualified as "current value" ?

I think, at least it should match 3 requirements.

  1. it must be different with "the previous value" (or "current value" is meaningless).
  2. it must be known about by the caller (or caller can not check whether fails or not).
  3. its meaning should not be conflict with "current value" (if "current value" is incorrect, it should be fail).

It seems only the parameter gid which caller inputs is qualified with
the 3 requirements.


> (FWIW, this behavior is awful and is probably the cause of a security
> bug or three, since success and failure are indistinguishable.  But I
> think your patch is wrong.)
> 

Hmm... at least, the original implementation is incorrect, and we need
discussing for this issues.


> --Andy
> 
> 

Thanks.
-- 
Chen Gang

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH] kernel/sys.c: improve the usage of return value
  2013-08-06  8:43     ` [PATCH] kernel/sys.c: improve the usage of return value Chen Gang
@ 2013-08-07 10:44       ` Chen Gang
  0 siblings, 0 replies; 26+ messages in thread
From: Chen Gang @ 2013-08-07 10:44 UTC (permalink / raw)
  To: Kees Cook, Al Viro, Oleg Nesterov, holt; +Cc: Andrew Morton, linux-kernel


According to the related discussion in another thread, this patch can be
obsoleted now.

Thanks.

On 08/06/2013 04:43 PM, Chen Gang wrote:
> Improve the usage of return value, so not only can make code clearer
> to readers, but also can improve the performance.
> 
> Assign the return error code only when error occurs, so can save some
> instructions.
> 
> For getcpu(), uname(), newuname(), and override_release(), can remove
> the return variable to make code clearer and save some instructions.
> 
> Also modify the related code to pass "./scripts/checkpatch.pl" checking.
> 
> 
> Signed-off-by: Chen Gang <gang.chen@asianux.com>
> ---
>  kernel/sys.c |  147 +++++++++++++++++++++++++++++++---------------------------
>  1 files changed, 79 insertions(+), 68 deletions(-)
> 
> diff --git a/kernel/sys.c b/kernel/sys.c
> index 771129b..a63a350 100644
> --- a/kernel/sys.c
> +++ b/kernel/sys.c
> @@ -386,13 +386,14 @@ SYSCALL_DEFINE1(setgid, gid_t, gid)
>  		return -ENOMEM;
>  	old = current_cred();
>  
> -	retval = -EPERM;
>  	if (nsown_capable(CAP_SETGID))
>  		new->gid = new->egid = new->sgid = new->fsgid = kgid;
>  	else if (gid_eq(kgid, old->gid) || gid_eq(kgid, old->sgid))
>  		new->egid = new->fsgid = kgid;
> -	else
> +	else {
> +		retval = -EPERM;
>  		goto error;
> +	}
>  
>  	return commit_creds(new);
>  
> @@ -533,7 +534,6 @@ SYSCALL_DEFINE1(setuid, uid_t, uid)
>  		return -ENOMEM;
>  	old = current_cred();
>  
> -	retval = -EPERM;
>  	if (nsown_capable(CAP_SETUID)) {
>  		new->suid = new->uid = kuid;
>  		if (!uid_eq(kuid, old->uid)) {
> @@ -542,6 +542,7 @@ SYSCALL_DEFINE1(setuid, uid_t, uid)
>  				goto error;
>  		}
>  	} else if (!uid_eq(kuid, old->uid) && !uid_eq(kuid, new->suid)) {
> +		retval = -EPERM;
>  		goto error;
>  	}
>  
> @@ -919,31 +920,35 @@ SYSCALL_DEFINE2(setpgid, pid_t, pid, pid_t, pgid)
>  	 */
>  	write_lock_irq(&tasklist_lock);
>  
> -	err = -ESRCH;
>  	p = find_task_by_vpid(pid);
> -	if (!p)
> +	if (!p) {
> +		err = -ESRCH;
>  		goto out;
> +	}
>  
> -	err = -EINVAL;
> -	if (!thread_group_leader(p))
> +	if (!thread_group_leader(p)) {
> +		err = -EINVAL;
>  		goto out;
> +	}
>  
>  	if (same_thread_group(p->real_parent, group_leader)) {
> -		err = -EPERM;
> -		if (task_session(p) != task_session(group_leader))
> +		if (task_session(p) != task_session(group_leader)) {
> +			err = -EPERM;
>  			goto out;
> -		err = -EACCES;
> -		if (p->did_exec)
> +		}
> +		if (p->did_exec) {
> +			err = -EACCES;
>  			goto out;
> -	} else {
> +		}
> +	} else if (p != group_leader) {
>  		err = -ESRCH;
> -		if (p != group_leader)
> -			goto out;
> +		goto out;
>  	}
>  
> -	err = -EPERM;
> -	if (p->signal->leader)
> +	if (p->signal->leader) {
> +		err = -EPERM;
>  		goto out;
> +	}
>  
>  	pgrp = task_pid(p);
>  	if (pgid != pid) {
> @@ -951,8 +956,10 @@ SYSCALL_DEFINE2(setpgid, pid_t, pid, pid_t, pgid)
>  
>  		pgrp = find_vpid(pgid);
>  		g = pid_task(pgrp, PIDTYPE_PGID);
> -		if (!g || task_session(g) != task_session(group_leader))
> +		if (!g || task_session(g) != task_session(group_leader)) {
> +			err = -EPERM;
>  			goto out;
> +		}
>  	}
>  
>  	err = security_task_setpgid(p, pgid);
> @@ -962,7 +969,6 @@ SYSCALL_DEFINE2(setpgid, pid_t, pid, pid_t, pgid)
>  	if (task_pgrp(p) != pgrp)
>  		change_pid(p, PIDTYPE_PGID, pgrp);
>  
> -	err = 0;
>  out:
>  	/* All paths lead to here, thus we are safe. -DaveM */
>  	write_unlock_irq(&tasklist_lock);
> @@ -980,14 +986,16 @@ SYSCALL_DEFINE1(getpgid, pid_t, pid)
>  	if (!pid)
>  		grp = task_pgrp(current);
>  	else {
> -		retval = -ESRCH;
>  		p = find_task_by_vpid(pid);
> -		if (!p)
> +		if (!p) {
> +			retval = -ESRCH;
>  			goto out;
> +		}
>  		grp = task_pgrp(p);
> -		if (!grp)
> +		if (!grp) {
> +			retval = -ESRCH;
>  			goto out;
> -
> +		}
>  		retval = security_task_getpgid(p);
>  		if (retval)
>  			goto out;
> @@ -1017,14 +1025,16 @@ SYSCALL_DEFINE1(getsid, pid_t, pid)
>  	if (!pid)
>  		sid = task_session(current);
>  	else {
> -		retval = -ESRCH;
>  		p = find_task_by_vpid(pid);
> -		if (!p)
> +		if (!p) {
> +			retval = -ESRCH;
>  			goto out;
> +		}
>  		sid = task_session(p);
> -		if (!sid)
> +		if (!sid) {
> +			retval = -ESRCH;
>  			goto out;
> -
> +		}
>  		retval = security_task_getsid(p);
>  		if (retval)
>  			goto out;
> @@ -1096,8 +1106,6 @@ DECLARE_RWSEM(uts_sem);
>   */
>  static int override_release(char __user *release, size_t len)
>  {
> -	int ret = 0;
> -
>  	if (current->personality & UNAME26) {
>  		const char *rest = UTS_RELEASE;
>  		char buf[65] = { 0 };
> @@ -1115,25 +1123,25 @@ static int override_release(char __user *release, size_t len)
>  		v = ((LINUX_VERSION_CODE >> 8) & 0xff) + 40;
>  		copy = clamp_t(size_t, len, 1, sizeof(buf));
>  		copy = scnprintf(buf, copy, "2.6.%u%s", v, rest);
> -		ret = copy_to_user(release, buf, copy + 1);
> +		return copy_to_user(release, buf, copy + 1);
>  	}
> -	return ret;
> +	return 0;
>  }
>  
>  SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name)
>  {
> -	int errno = 0;
> -
>  	down_read(&uts_sem);
> -	if (copy_to_user(name, utsname(), sizeof *name))
> -		errno = -EFAULT;
> +	if (copy_to_user(name, utsname(), sizeof(*name))) {
> +		up_read(&uts_sem);
> +		return -EFAULT;
> +	}
>  	up_read(&uts_sem);
>  
> -	if (!errno && override_release(name->release, sizeof(name->release)))
> -		errno = -EFAULT;
> -	if (!errno && override_architecture(name))
> -		errno = -EFAULT;
> -	return errno;
> +	if (override_release(name->release, sizeof(name->release)))
> +		return -EFAULT;
> +	if (override_architecture(name))
> +		return -EFAULT;
> +	return 0;
>  }
>  
>  #ifdef __ARCH_WANT_SYS_OLD_UNAME
> @@ -1142,21 +1150,21 @@ SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name)
>   */
>  SYSCALL_DEFINE1(uname, struct old_utsname __user *, name)
>  {
> -	int error = 0;
> -
>  	if (!name)
>  		return -EFAULT;
>  
>  	down_read(&uts_sem);
> -	if (copy_to_user(name, utsname(), sizeof(*name)))
> -		error = -EFAULT;
> +	if (copy_to_user(name, utsname(), sizeof(*name))) {
> +		up_read(&uts_sem);
> +		return -EFAULT;
> +	}
>  	up_read(&uts_sem);
>  
> -	if (!error && override_release(name->release, sizeof(name->release)))
> -		error = -EFAULT;
> -	if (!error && override_architecture(name))
> -		error = -EFAULT;
> -	return error;
> +	if (override_release(name->release, sizeof(name->release)))
> +		return -EFAULT;
> +	if (override_architecture(name))
> +		return -EFAULT;
> +	return 0;
>  }
>  
>  SYSCALL_DEFINE1(olduname, struct oldold_utsname __user *, name)
> @@ -1185,12 +1193,14 @@ SYSCALL_DEFINE1(olduname, struct oldold_utsname __user *, name)
>  				__OLD_UTS_LEN);
>  	error |= __put_user(0, name->machine + __OLD_UTS_LEN);
>  	up_read(&uts_sem);
> +	if (error)
> +		return -EFAULT;
>  
> -	if (!error && override_architecture(name))
> -		error = -EFAULT;
> -	if (!error && override_release(name->release, sizeof(name->release)))
> -		error = -EFAULT;
> -	return error ? -EFAULT : 0;
> +	if (override_architecture(name))
> +		return -EFAULT;
> +	if (override_release(name->release, sizeof(name->release)))
> +		return -EFAULT;
> +	return 0;
>  }
>  #endif
>  
> @@ -1648,10 +1658,11 @@ static int prctl_set_mm_exe_file(struct mm_struct *mm, unsigned int fd)
>  	 * sure that this one is executable as well, to avoid breaking an
>  	 * overall picture.
>  	 */
> -	err = -EACCES;
> -	if (!S_ISREG(inode->i_mode)	||
> -	    exe.file->f_path.mnt->mnt_flags & MNT_NOEXEC)
> +	if (!S_ISREG(inode->i_mode) ||
> +	    exe.file->f_path.mnt->mnt_flags & MNT_NOEXEC) {
> +		err = -EACCES;
>  		goto exit;
> +	}
>  
>  	err = inode_permission(inode, MAY_EXEC);
>  	if (err)
> @@ -1662,15 +1673,16 @@ static int prctl_set_mm_exe_file(struct mm_struct *mm, unsigned int fd)
>  	/*
>  	 * Forbid mm->exe_file change if old file still mapped.
>  	 */
> -	err = -EBUSY;
>  	if (mm->exe_file) {
>  		struct vm_area_struct *vma;
>  
>  		for (vma = mm->mmap; vma; vma = vma->vm_next)
>  			if (vma->vm_file &&
>  			    path_equal(&vma->vm_file->f_path,
> -				       &mm->exe_file->f_path))
> +				       &mm->exe_file->f_path)) {
> +				err = -EBUSY;
>  				goto exit_unlock;
> +			}
>  	}
>  
>  	/*
> @@ -1679,11 +1691,10 @@ static int prctl_set_mm_exe_file(struct mm_struct *mm, unsigned int fd)
>  	 * could make a snapshot over all processes running and monitor
>  	 * /proc/pid/exe changes to notice unusual activity if needed.
>  	 */
> -	err = -EPERM;
> -	if (test_and_set_bit(MMF_EXE_FILE_CHANGED, &mm->flags))
> +	if (test_and_set_bit(MMF_EXE_FILE_CHANGED, &mm->flags)) {
> +		err = -EPERM;
>  		goto exit_unlock;
> -
> -	err = 0;
> +	}
>  	set_mm_exe_file(mm, exe.file);	/* this grabs a reference to exe.file */
>  exit_unlock:
>  	up_write(&mm->mmap_sem);
> @@ -2009,13 +2020,13 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
>  SYSCALL_DEFINE3(getcpu, unsigned __user *, cpup, unsigned __user *, nodep,
>  		struct getcpu_cache __user *, unused)
>  {
> -	int err = 0;
>  	int cpu = raw_smp_processor_id();
> -	if (cpup)
> -		err |= put_user(cpu, cpup);
> -	if (nodep)
> -		err |= put_user(cpu_to_node(cpu), nodep);
> -	return err ? -EFAULT : 0;
> +
> +	if (cpup && put_user(cpu, cpup))
> +		return -EFAULT;
> +	if (nodep && put_user(cpu_to_node(cpu), nodep))
> +		return -EFAULT;
> +	return 0;
>  }
>  
>  /**
> 


-- 
Chen Gang

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 1/2] kernel/sys.c: return the current gid when error occurs
  2013-08-06 20:21   ` Andy Lutomirski
  2013-08-07  3:30     ` Chen Gang
@ 2013-08-07 16:21     ` Oleg Nesterov
  2013-08-07 16:58       ` Andy Lutomirski
  2013-08-08 13:37       ` Michael Kerrisk (man-pages)
  1 sibling, 2 replies; 26+ messages in thread
From: Oleg Nesterov @ 2013-08-07 16:21 UTC (permalink / raw)
  To: Andy Lutomirski, Michael Kerrisk
  Cc: Chen Gang, Kees Cook, Al Viro, holt, Andrew Morton, linux-kernel

On 08/06, Andy Lutomirski wrote:
>
> I assume that what the man page means is that the return value is
> whatever fsgid was prior to the call.  On error, fsgid isn't changed, so
> the return value is still "current".

Probably... Still

	On success, the previous value of fsuid is returned.
	On error, the current value of fsuid is returned.

looks confusing. sys_setfsuid() always returns the old value.

> (FWIW, this behavior is awful and is probably the cause of a security
> bug or three, since success and failure are indistinguishable.

At least this all looks strange.

I dunno if we can change this old behaviour. I won't be surprized
if someone already uses setfsuid(-1) as getfsuid().

And perhaps the man page should be changed. Add Michael.

Oleg.


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 1/2] kernel/sys.c: return the current gid when error occurs
  2013-08-07 16:21     ` Oleg Nesterov
@ 2013-08-07 16:58       ` Andy Lutomirski
  2013-08-08  1:30         ` Chen Gang
  2013-08-08 13:37       ` Michael Kerrisk (man-pages)
  1 sibling, 1 reply; 26+ messages in thread
From: Andy Lutomirski @ 2013-08-07 16:58 UTC (permalink / raw)
  To: Oleg Nesterov
  Cc: Michael Kerrisk, Chen Gang, Kees Cook, Al Viro, holt,
	Andrew Morton, linux-kernel

On Wed, Aug 7, 2013 at 9:21 AM, Oleg Nesterov <oleg@redhat.com> wrote:
> On 08/06, Andy Lutomirski wrote:
>>
>> I assume that what the man page means is that the return value is
>> whatever fsgid was prior to the call.  On error, fsgid isn't changed, so
>> the return value is still "current".
>
> Probably... Still
>
>         On success, the previous value of fsuid is returned.
>         On error, the current value of fsuid is returned.
>
> looks confusing. sys_setfsuid() always returns the old value.
>
>> (FWIW, this behavior is awful and is probably the cause of a security
>> bug or three, since success and failure are indistinguishable.
>
> At least this all looks strange.
>
> I dunno if we can change this old behaviour. I won't be surprized
> if someone already uses setfsuid(-1) as getfsuid().

I suspect that changing this without introducing security or other
bugs is impossible.  If someone wanted to add new_setfsuid that
returned an error when it failed, that would be a different story.
(I'm not going to do that myself.)

>
> And perhaps the man page should be changed. Add Michael.

Agreed.  The text is a bit odd.

>
> Oleg.
>



-- 
Andy Lutomirski
AMA Capital Management, LLC

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 1/2] kernel/sys.c: return the current gid when error occurs
  2013-08-07 16:58       ` Andy Lutomirski
@ 2013-08-08  1:30         ` Chen Gang
  2013-08-08  1:35           ` Andy Lutomirski
  0 siblings, 1 reply; 26+ messages in thread
From: Chen Gang @ 2013-08-08  1:30 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Oleg Nesterov, Michael Kerrisk, Kees Cook, Al Viro, holt,
	Andrew Morton, linux-kernel

On 08/08/2013 12:58 AM, Andy Lutomirski wrote:
> On Wed, Aug 7, 2013 at 9:21 AM, Oleg Nesterov <oleg@redhat.com> wrote:
>> On 08/06, Andy Lutomirski wrote:
>>>
>>> I assume that what the man page means is that the return value is
>>> whatever fsgid was prior to the call.  On error, fsgid isn't changed, so
>>> the return value is still "current".
>>
>> Probably... Still
>>
>>         On success, the previous value of fsuid is returned.
>>         On error, the current value of fsuid is returned.
>>
>> looks confusing. sys_setfsuid() always returns the old value.
>>
>>> (FWIW, this behavior is awful and is probably the cause of a security
>>> bug or three, since success and failure are indistinguishable.
>>
>> At least this all looks strange.
>>
>> I dunno if we can change this old behaviour. I won't be surprized
>> if someone already uses setfsuid(-1) as getfsuid().
> 

Oh, really it is.

Hmm... as a pair function, we need add getfsuid() too, if we do not add
it, it will make negative effect with setfsuid().

Since it is a system call, we have to keep compitable.

So in my opinion, better add getfsuid2()/setfsuid2() instead of current
setfsuid()

  for getfsuid2() can just reference to getuid() definition.
  for setfsuid2() can just reference to setuid() definition.
    (which can return error code when failure occurs).

If possible, I will/should sent the related patches for it.

> I suspect that changing this without introducing security or other
> bugs is impossible.  If someone wanted to add new_setfsuid that
> returned an error when it failed, that would be a different story.
> (I'm not going to do that myself.)
> 
>>
>> And perhaps the man page should be changed. Add Michael.
> 
> Agreed.  The text is a bit odd.
> 

I agree that the text is odd, since it is an system call API, we have
to change it to match our current kernel implementation which is:

  "for system call, whether succeed or not, it always return the previous value, the caller can not know whether succeed or not directly"
  "if the caller need know about success or not, the demo like below"
  "	setfsuid(new);"
  "	if (setfsuid(-1) != new)"
  "		/* report failure */" 

And better to give an additional comment:

  "currently, new system call getfsuid2()/setfsuid2() are supplied, setfsuid() is obseleted"

>>
>> Oleg.
>>
> 
> 
> 

Thanks.
-- 
Chen Gang

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 1/2] kernel/sys.c: return the current gid when error occurs
  2013-08-08  1:30         ` Chen Gang
@ 2013-08-08  1:35           ` Andy Lutomirski
  2013-08-08  1:48             ` Chen Gang
  0 siblings, 1 reply; 26+ messages in thread
From: Andy Lutomirski @ 2013-08-08  1:35 UTC (permalink / raw)
  To: Chen Gang
  Cc: Oleg Nesterov, Michael Kerrisk, Kees Cook, Al Viro, holt,
	Andrew Morton, linux-kernel

On Wed, Aug 7, 2013 at 6:30 PM, Chen Gang <gang.chen@asianux.com> wrote:
> On 08/08/2013 12:58 AM, Andy Lutomirski wrote:
>> On Wed, Aug 7, 2013 at 9:21 AM, Oleg Nesterov <oleg@redhat.com> wrote:
>>> On 08/06, Andy Lutomirski wrote:
>>>>
>>>> I assume that what the man page means is that the return value is
>>>> whatever fsgid was prior to the call.  On error, fsgid isn't changed, so
>>>> the return value is still "current".
>>>
>>> Probably... Still
>>>
>>>         On success, the previous value of fsuid is returned.
>>>         On error, the current value of fsuid is returned.
>>>
>>> looks confusing. sys_setfsuid() always returns the old value.
>>>
>>>> (FWIW, this behavior is awful and is probably the cause of a security
>>>> bug or three, since success and failure are indistinguishable.
>>>
>>> At least this all looks strange.
>>>
>>> I dunno if we can change this old behaviour. I won't be surprized
>>> if someone already uses setfsuid(-1) as getfsuid().
>>
>
> Oh, really it is.
>
> Hmm... as a pair function, we need add getfsuid() too, if we do not add
> it, it will make negative effect with setfsuid().
>
> Since it is a system call, we have to keep compitable.
>
> So in my opinion, better add getfsuid2()/setfsuid2() instead of current
> setfsuid()

How about getfsuid() and setfsuid2()?

--Andy

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 1/2] kernel/sys.c: return the current gid when error occurs
  2013-08-08  1:35           ` Andy Lutomirski
@ 2013-08-08  1:48             ` Chen Gang
  2013-08-08 13:52               ` Michael Kerrisk (man-pages)
  0 siblings, 1 reply; 26+ messages in thread
From: Chen Gang @ 2013-08-08  1:48 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Oleg Nesterov, Michael Kerrisk, Kees Cook, Al Viro, holt,
	Andrew Morton, linux-kernel

On 08/08/2013 09:35 AM, Andy Lutomirski wrote:
> On Wed, Aug 7, 2013 at 6:30 PM, Chen Gang <gang.chen@asianux.com> wrote:
>> On 08/08/2013 12:58 AM, Andy Lutomirski wrote:
>>> On Wed, Aug 7, 2013 at 9:21 AM, Oleg Nesterov <oleg@redhat.com> wrote:
>>>> On 08/06, Andy Lutomirski wrote:
>>>>>
>>>>> I assume that what the man page means is that the return value is
>>>>> whatever fsgid was prior to the call.  On error, fsgid isn't changed, so
>>>>> the return value is still "current".
>>>>
>>>> Probably... Still
>>>>
>>>>         On success, the previous value of fsuid is returned.
>>>>         On error, the current value of fsuid is returned.
>>>>
>>>> looks confusing. sys_setfsuid() always returns the old value.
>>>>
>>>>> (FWIW, this behavior is awful and is probably the cause of a security
>>>>> bug or three, since success and failure are indistinguishable.
>>>>
>>>> At least this all looks strange.
>>>>
>>>> I dunno if we can change this old behaviour. I won't be surprized
>>>> if someone already uses setfsuid(-1) as getfsuid().
>>>
>>
>> Oh, really it is.
>>
>> Hmm... as a pair function, we need add getfsuid() too, if we do not add
>> it, it will make negative effect with setfsuid().
>>
>> Since it is a system call, we have to keep compitable.
>>
>> So in my opinion, better add getfsuid2()/setfsuid2() instead of current
>> setfsuid()
> 
> How about getfsuid() and setfsuid2()?
> 

Hmm... I have 2 reasons, please check.

1st reason: I checked history (just like Kees Cook suggested),
getfsuid() is mentioned before (you can google to find it), so need use
getfsuid2() to bypass the history complex.

And 2nd reason: getfsuid() seems more like the pair of setfsuid(), not
for setfsuid2().



> --Andy
> 
> 

Thanks.
-- 
Chen Gang

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 1/2] kernel/sys.c: return the current gid when error occurs
  2013-08-07 16:21     ` Oleg Nesterov
  2013-08-07 16:58       ` Andy Lutomirski
@ 2013-08-08 13:37       ` Michael Kerrisk (man-pages)
  2013-08-09  0:59         ` Chen Gang
  1 sibling, 1 reply; 26+ messages in thread
From: Michael Kerrisk (man-pages) @ 2013-08-08 13:37 UTC (permalink / raw)
  To: Oleg Nesterov
  Cc: Andy Lutomirski, Michael Kerrisk, Chen Gang, Kees Cook, Al Viro,
	holt, Andrew Morton, linux-kernel

On 08/07/13 18:21, Oleg Nesterov wrote:
> On 08/06, Andy Lutomirski wrote:
>>
>> I assume that what the man page means is that the return value is
>> whatever fsgid was prior to the call.  On error, fsgid isn't changed, so
>> the return value is still "current".
> 
> Probably... Still
> 
> 	On success, the previous value of fsuid is returned.
> 	On error, the current value of fsuid is returned.
> 
> looks confusing. sys_setfsuid() always returns the old value.
> 
>> (FWIW, this behavior is awful and is probably the cause of a security
>> bug or three, since success and failure are indistinguishable.
> 
> At least this all looks strange.
> 
> I dunno if we can change this old behaviour. I won't be surprized
> if someone already uses setfsuid(-1) as getfsuid().
> 
> And perhaps the man page should be changed. Add Michael.

Thanks, Oleg. I've applied the following patch to setfsuid.2
(and a similar patch to setfsgid.2).

Cheers,

Michael

--- a/man2/setfsuid.2
+++ b/man2/setfsuid.2
@@ -67,12 +67,8 @@ matches either the real user ID, effective user ID, saved set-user-ID, or
 the current value of
 .IR fsuid .
 .SH RETURN VALUE
-On success, the previous value of
-.I fsuid
-is returned.
-On error, the current value of
-.I fsuid
-is returned.
+On both success and failure,
+this call returns the previous filesystem user ID of the caller.
 .SH VERSIONS
 This system call is present in Linux since version 1.2.
 .\" This system call is present since Linux 1.1.44
@@ -102,7 +98,16 @@ The glibc
 .BR setfsuid ()
 wrapper function transparently deals with the variation across kernel versions.
 .SH BUGS
-No error messages of any kind are returned to the caller.
+No error indications of any kind are returned to the caller,
+and the fact that both successful and unsuccessful calls return
+the same value makes it impossible to directly determine
+whether the call succeeded or failed.
+Instead, the caller must resort to looking at the return value
+from a further call such as
+.IR setfsuid(\-1)
+(which will always fail), in order to determine if a preceding call to
+.BR setfsuid ()
+changed the filesystem user ID.
 At the very
 least,
 .B EPERM



^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 1/2] kernel/sys.c: return the current gid when error occurs
  2013-08-08  1:48             ` Chen Gang
@ 2013-08-08 13:52               ` Michael Kerrisk (man-pages)
  2013-08-09  0:55                 ` Chen Gang
  0 siblings, 1 reply; 26+ messages in thread
From: Michael Kerrisk (man-pages) @ 2013-08-08 13:52 UTC (permalink / raw)
  To: Chen Gang
  Cc: Andy Lutomirski, Oleg Nesterov, Michael Kerrisk, Kees Cook,
	Al Viro, holt, Andrew Morton, linux-kernel

On 08/08/13 03:48, Chen Gang wrote:
> On 08/08/2013 09:35 AM, Andy Lutomirski wrote:
>> On Wed, Aug 7, 2013 at 6:30 PM, Chen Gang <gang.chen@asianux.com> wrote:
>>> On 08/08/2013 12:58 AM, Andy Lutomirski wrote:
>>>> On Wed, Aug 7, 2013 at 9:21 AM, Oleg Nesterov <oleg@redhat.com> wrote:
>>>>> On 08/06, Andy Lutomirski wrote:
>>>>>>
>>>>>> I assume that what the man page means is that the return value is
>>>>>> whatever fsgid was prior to the call.  On error, fsgid isn't changed, so
>>>>>> the return value is still "current".
>>>>>
>>>>> Probably... Still
>>>>>
>>>>>         On success, the previous value of fsuid is returned.
>>>>>         On error, the current value of fsuid is returned.
>>>>>
>>>>> looks confusing. sys_setfsuid() always returns the old value.
>>>>>
>>>>>> (FWIW, this behavior is awful and is probably the cause of a security
>>>>>> bug or three, since success and failure are indistinguishable.
>>>>>
>>>>> At least this all looks strange.
>>>>>
>>>>> I dunno if we can change this old behaviour. I won't be surprized
>>>>> if someone already uses setfsuid(-1) as getfsuid().
>>>>
>>>
>>> Oh, really it is.
>>>
>>> Hmm... as a pair function, we need add getfsuid() too, if we do not add
>>> it, it will make negative effect with setfsuid().
>>>
>>> Since it is a system call, we have to keep compitable.
>>>
>>> So in my opinion, better add getfsuid2()/setfsuid2() instead of current
>>> setfsuid()
>>
>> How about getfsuid() and setfsuid2()?
>>
> 
> Hmm... I have 2 reasons, please check.
> 
> 1st reason: I checked history (just like Kees Cook suggested),
> getfsuid() is mentioned before (you can google to find it), so need use
> getfsuid2() to bypass the history complex.
> 
> And 2nd reason: getfsuid() seems more like the pair of setfsuid(), not
> for setfsuid2().

Time to apply the brakes... *Why* add new system calls here? I don't 
think there is any good reason. Yes, the existing APIs are rubbish,
but, as far as I can tell, they are also obsolete and unneeded.
The fsuid/fsgid mechanism was a bizarre Linuxism whose only purpose
was (as far as I know), to allow for the fact that Linux long ago
applied nonstandard rules when determining when one process could 
send signals to another. Quoting some book on the subject:

    Why does Linux provide the file-system IDs and in what 
    circumstances would we want the effective and file-system 
    IDs to differ? The reasons are primarily historical.
    The file-system IDs first appeared in Linux 1.2. In 
    that kernel version, one process could send a signal to 
    another if the effective user ID of the sender matched
    the real or effective user ID of the target process. 
    This affected certain programs such as the Linux NFS 
    (Network File System) server program, which needed to be
    able to access files as though it had the effective IDs 
    of the corresponding client process. However, if the NFS 
    server changed its effective user ID, it would be 
    vulnerable to signals from unprivileged user processes. 
    To prevent this possibility, the separate file-system user
    and group IDs were devised. By leaving its effective IDs
    unchanged, but changing its file-system IDs, the NFS 
    server could masquerade as another user for the purpose of 
    accessing files without being vulnerable to signals from
    user processes.

    From kernel 2.0 onward, Linux adopted the SUSv3-mandated 
    rules regarding permission for sending signals, and these 
    rules don't involve the effective user ID of the target
    process. Thus, the file-system ID feature is no longer 
    strictly necessary (a process can nowadays achieve the 
    desired results by making judicious use of the system
    calls described later in this chapter to change
    the value of the effective user ID to and from an
    unprivileged value, as required), but it remains for
    compatibility with existing software.

So, I don't think anything needs fixing: there should be no 
new users of these system calls anyway.

Cheers,

Michael


-- 
Michael Kerrisk Linux man-pages maintainer;
http://www.kernel.org/doc/man-pages/
Author of "The Linux Programming Interface", http://blog.man7.org/


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 1/2] kernel/sys.c: return the current gid when error occurs
  2013-08-08 13:52               ` Michael Kerrisk (man-pages)
@ 2013-08-09  0:55                 ` Chen Gang
  0 siblings, 0 replies; 26+ messages in thread
From: Chen Gang @ 2013-08-09  0:55 UTC (permalink / raw)
  To: Michael Kerrisk (man-pages)
  Cc: Andy Lutomirski, Oleg Nesterov, Kees Cook, Al Viro, holt,
	Andrew Morton, linux-kernel

On 08/08/2013 09:52 PM, Michael Kerrisk (man-pages) wrote:
> On 08/08/13 03:48, Chen Gang wrote:
>> On 08/08/2013 09:35 AM, Andy Lutomirski wrote:
>>> On Wed, Aug 7, 2013 at 6:30 PM, Chen Gang <gang.chen@asianux.com> wrote:
>>>> On 08/08/2013 12:58 AM, Andy Lutomirski wrote:
>>>>> On Wed, Aug 7, 2013 at 9:21 AM, Oleg Nesterov <oleg@redhat.com> wrote:
>>>>>> On 08/06, Andy Lutomirski wrote:
>>>>>>>
>>>>>>> I assume that what the man page means is that the return value is
>>>>>>> whatever fsgid was prior to the call.  On error, fsgid isn't changed, so
>>>>>>> the return value is still "current".
>>>>>>
>>>>>> Probably... Still
>>>>>>
>>>>>>         On success, the previous value of fsuid is returned.
>>>>>>         On error, the current value of fsuid is returned.
>>>>>>
>>>>>> looks confusing. sys_setfsuid() always returns the old value.
>>>>>>
>>>>>>> (FWIW, this behavior is awful and is probably the cause of a security
>>>>>>> bug or three, since success and failure are indistinguishable.
>>>>>>
>>>>>> At least this all looks strange.
>>>>>>
>>>>>> I dunno if we can change this old behaviour. I won't be surprized
>>>>>> if someone already uses setfsuid(-1) as getfsuid().
>>>>>
>>>>
>>>> Oh, really it is.
>>>>
>>>> Hmm... as a pair function, we need add getfsuid() too, if we do not add
>>>> it, it will make negative effect with setfsuid().
>>>>
>>>> Since it is a system call, we have to keep compitable.
>>>>
>>>> So in my opinion, better add getfsuid2()/setfsuid2() instead of current
>>>> setfsuid()
>>>
>>> How about getfsuid() and setfsuid2()?
>>>
>>
>> Hmm... I have 2 reasons, please check.
>>
>> 1st reason: I checked history (just like Kees Cook suggested),
>> getfsuid() is mentioned before (you can google to find it), so need use
>> getfsuid2() to bypass the history complex.
>>
>> And 2nd reason: getfsuid() seems more like the pair of setfsuid(), not
>> for setfsuid2().
> 
> Time to apply the brakes... *Why* add new system calls here? I don't 
> think there is any good reason. Yes, the existing APIs are rubbish,
> but, as far as I can tell, they are also obsolete and unneeded.
> The fsuid/fsgid mechanism was a bizarre Linuxism whose only purpose
> was (as far as I know), to allow for the fact that Linux long ago
> applied nonstandard rules when determining when one process could 
> send signals to another. Quoting some book on the subject:
> 
>     Why does Linux provide the file-system IDs and in what 
>     circumstances would we want the effective and file-system 
>     IDs to differ? The reasons are primarily historical.
>     The file-system IDs first appeared in Linux 1.2. In 
>     that kernel version, one process could send a signal to 
>     another if the effective user ID of the sender matched
>     the real or effective user ID of the target process. 
>     This affected certain programs such as the Linux NFS 
>     (Network File System) server program, which needed to be
>     able to access files as though it had the effective IDs 
>     of the corresponding client process. However, if the NFS 
>     server changed its effective user ID, it would be 
>     vulnerable to signals from unprivileged user processes. 
>     To prevent this possibility, the separate file-system user
>     and group IDs were devised. By leaving its effective IDs
>     unchanged, but changing its file-system IDs, the NFS 
>     server could masquerade as another user for the purpose of 
>     accessing files without being vulnerable to signals from
>     user processes.
> 
>     From kernel 2.0 onward, Linux adopted the SUSv3-mandated 
>     rules regarding permission for sending signals, and these 
>     rules don't involve the effective user ID of the target
>     process. Thus, the file-system ID feature is no longer 
>     strictly necessary (a process can nowadays achieve the 
>     desired results by making judicious use of the system
>     calls described later in this chapter to change
>     the value of the effective user ID to and from an
>     unprivileged value, as required), but it remains for
>     compatibility with existing software.
> 
> So, I don't think anything needs fixing: there should be no 
> new users of these system calls anyway.
> 

OK, thank you for your details, at least for me, what you says above
sounds reasonable.

> Cheers,
> 
> Michael
> 
> 

Thanks.
-- 
Chen Gang

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 1/2] kernel/sys.c: return the current gid when error occurs
  2013-08-08 13:37       ` Michael Kerrisk (man-pages)
@ 2013-08-09  0:59         ` Chen Gang
  2013-08-09  7:27           ` Michael Kerrisk (man-pages)
  0 siblings, 1 reply; 26+ messages in thread
From: Chen Gang @ 2013-08-09  0:59 UTC (permalink / raw)
  To: Michael Kerrisk (man-pages)
  Cc: Oleg Nesterov, Andy Lutomirski, Kees Cook, Al Viro, holt,
	Andrew Morton, linux-kernel

On 08/08/2013 09:37 PM, Michael Kerrisk (man-pages) wrote:
> On 08/07/13 18:21, Oleg Nesterov wrote:
>> On 08/06, Andy Lutomirski wrote:
>>>
>>> I assume that what the man page means is that the return value is
>>> whatever fsgid was prior to the call.  On error, fsgid isn't changed, so
>>> the return value is still "current".
>>
>> Probably... Still
>>
>> 	On success, the previous value of fsuid is returned.
>> 	On error, the current value of fsuid is returned.
>>
>> looks confusing. sys_setfsuid() always returns the old value.
>>
>>> (FWIW, this behavior is awful and is probably the cause of a security
>>> bug or three, since success and failure are indistinguishable.
>>
>> At least this all looks strange.
>>
>> I dunno if we can change this old behaviour. I won't be surprized
>> if someone already uses setfsuid(-1) as getfsuid().
>>
>> And perhaps the man page should be changed. Add Michael.
> 
> Thanks, Oleg. I've applied the following patch to setfsuid.2
> (and a similar patch to setfsgid.2).
> 
> Cheers,
> 
> Michael
> 
> --- a/man2/setfsuid.2
> +++ b/man2/setfsuid.2
> @@ -67,12 +67,8 @@ matches either the real user ID, effective user ID, saved set-user-ID, or
>  the current value of
>  .IR fsuid .
>  .SH RETURN VALUE
> -On success, the previous value of
> -.I fsuid
> -is returned.
> -On error, the current value of
> -.I fsuid
> -is returned.
> +On both success and failure,
> +this call returns the previous filesystem user ID of the caller.
>  .SH VERSIONS
>  This system call is present in Linux since version 1.2.
>  .\" This system call is present since Linux 1.1.44
> @@ -102,7 +98,16 @@ The glibc
>  .BR setfsuid ()
>  wrapper function transparently deals with the variation across kernel versions.
>  .SH BUGS
> -No error messages of any kind are returned to the caller.
> +No error indications of any kind are returned to the caller,
> +and the fact that both successful and unsuccessful calls return
> +the same value makes it impossible to directly determine
> +whether the call succeeded or failed.
> +Instead, the caller must resort to looking at the return value
> +from a further call such as
> +.IR setfsuid(\-1)
> +(which will always fail), in order to determine if a preceding call to
> +.BR setfsuid ()
> +changed the filesystem user ID.
>  At the very
>  least,
>  .B EPERM
> 

Is it suitable to mention this API is obsoleted and unneeded in man page
?  ;-)


Thanks.
-- 
Chen Gang

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 1/2] kernel/sys.c: return the current gid when error occurs
  2013-08-09  0:59         ` Chen Gang
@ 2013-08-09  7:27           ` Michael Kerrisk (man-pages)
  0 siblings, 0 replies; 26+ messages in thread
From: Michael Kerrisk (man-pages) @ 2013-08-09  7:27 UTC (permalink / raw)
  To: Chen Gang
  Cc: Michael Kerrisk (man-pages),
	Oleg Nesterov, Andy Lutomirski, Kees Cook, Al Viro, holt,
	Andrew Morton, linux-kernel

On 08/09/13 02:59, Chen Gang wrote:
> On 08/08/2013 09:37 PM, Michael Kerrisk (man-pages) wrote:
>> On 08/07/13 18:21, Oleg Nesterov wrote:
>>> On 08/06, Andy Lutomirski wrote:
>>>>
>>>> I assume that what the man page means is that the return value is
>>>> whatever fsgid was prior to the call.  On error, fsgid isn't changed, so
>>>> the return value is still "current".
>>>
>>> Probably... Still
>>>
>>> 	On success, the previous value of fsuid is returned.
>>> 	On error, the current value of fsuid is returned.
>>>
>>> looks confusing. sys_setfsuid() always returns the old value.
>>>
>>>> (FWIW, this behavior is awful and is probably the cause of a security
>>>> bug or three, since success and failure are indistinguishable.
>>>
>>> At least this all looks strange.
>>>
>>> I dunno if we can change this old behaviour. I won't be surprized
>>> if someone already uses setfsuid(-1) as getfsuid().
>>>
>>> And perhaps the man page should be changed. Add Michael.
>>
>> Thanks, Oleg. I've applied the following patch to setfsuid.2
>> (and a similar patch to setfsgid.2).
>>
>> Cheers,
>>
>> Michael
>>
>> --- a/man2/setfsuid.2
>> +++ b/man2/setfsuid.2
>> @@ -67,12 +67,8 @@ matches either the real user ID, effective user ID, saved set-user-ID, or
>>  the current value of
>>  .IR fsuid .
>>  .SH RETURN VALUE
>> -On success, the previous value of
>> -.I fsuid
>> -is returned.
>> -On error, the current value of
>> -.I fsuid
>> -is returned.
>> +On both success and failure,
>> +this call returns the previous filesystem user ID of the caller.
>>  .SH VERSIONS
>>  This system call is present in Linux since version 1.2.
>>  .\" This system call is present since Linux 1.1.44
>> @@ -102,7 +98,16 @@ The glibc
>>  .BR setfsuid ()
>>  wrapper function transparently deals with the variation across kernel versions.
>>  .SH BUGS
>> -No error messages of any kind are returned to the caller.
>> +No error indications of any kind are returned to the caller,
>> +and the fact that both successful and unsuccessful calls return
>> +the same value makes it impossible to directly determine
>> +whether the call succeeded or failed.
>> +Instead, the caller must resort to looking at the return value
>> +from a further call such as
>> +.IR setfsuid(\-1)
>> +(which will always fail), in order to determine if a preceding call to
>> +.BR setfsuid ()
>> +changed the filesystem user ID.
>>  At the very
>>  least,
>>  .B EPERM
>>
> 
> Is it suitable to mention this API is obsoleted and unneeded in man page
> ?  ;-)

Yes, that seems reasonable. Done.

Cheers,

Michael



^ permalink raw reply	[flat|nested] 26+ messages in thread

end of thread, other threads:[~2013-08-09  7:38 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-08-06  8:00 [PATCH 0/2] kernel/sys.c: for setfsgid(), return the current gid when error occurs Chen Gang
2013-08-06  8:01 ` [PATCH 1/2] kernel/sys.c: " Chen Gang
2013-08-06 20:21   ` Andy Lutomirski
2013-08-07  3:30     ` Chen Gang
2013-08-07 16:21     ` Oleg Nesterov
2013-08-07 16:58       ` Andy Lutomirski
2013-08-08  1:30         ` Chen Gang
2013-08-08  1:35           ` Andy Lutomirski
2013-08-08  1:48             ` Chen Gang
2013-08-08 13:52               ` Michael Kerrisk (man-pages)
2013-08-09  0:55                 ` Chen Gang
2013-08-08 13:37       ` Michael Kerrisk (man-pages)
2013-08-09  0:59         ` Chen Gang
2013-08-09  7:27           ` Michael Kerrisk (man-pages)
2013-08-06  8:02 ` [PATCH 2/2] kernel/sys.c: remove useless variable 'old_fsgid' for setfsgid() Chen Gang
2013-08-06  8:56   ` Chen Gang
2013-08-06  8:13 ` kernel/sys.c: for setfsuid(), return the current uid when error occurs Chen Gang
2013-08-06  8:14   ` Chen Gang
2013-08-06  8:15   ` [PATCH 0/2] " Chen Gang
2013-08-06  8:15     ` [PATCH 1/2] kernel/sys.c: " Chen Gang
2013-08-06  8:16     ` [PATCH 2/2] kernel/sys.c: remove useless variable 'old_fsuid' for setfsuid() Chen Gang
2013-08-06  8:55       ` Chen Gang
2013-08-06  8:43     ` [PATCH] kernel/sys.c: improve the usage of return value Chen Gang
2013-08-07 10:44       ` Chen Gang
2013-08-06 18:36 ` [PATCH 0/2] kernel/sys.c: for setfsgid(), return the current gid when error occurs Kees Cook
2013-08-07  2:25   ` Chen Gang

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.