kernel/sys.c: for setfsgid(), return the current gid when error occurs
cover kernel/sys.c: for setfsgid(), return the current gid when error occurs
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'.
--
kernel/sys.c | 15 +++++---------- 1 files changed, 5 insertions(+), 10 deletions(-)
PATCH 1/2 kernel/sys.c: return the current gid when error occurs
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.
--- kernel/sys.c | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-)
kernel/sys.c +3 -3
@@ -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);
Signature · 1 line
1.7.7.6
Re: [PATCH 1/2] kernel/sys.c: return the current gid when error occurs
Quoted 18 lines · Chen Gang
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 <[email protected]>--- kernel/sys.c | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-)kernel/sys.c +0
-0
kernel/sys.c SYSCALL_DEFINE1(setfsgid, gid_t, gid) · line 778
Quoted 5 lines
kernel/sys.c +1
-1@@ -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
Re: [PATCH 1/2] kernel/sys.c: return the current gid when error occurs
Quoted 20 lines · Andy Lutomirski
Quoted 19 lines · Chen Gang
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 <[email protected]>--- kernel/sys.c | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-)kernel/sys.c +0
-0@@ -775,11 +775,11 @@ SYSCALL_DEFINE1(setfsgid, gid_t, gid)
Quoted 8 lines
kernel/sys.c SYSCALL_DEFINE1(setfsgid, gid_t, gid) · line 778
Quoted 4 lines
kernel/sys.c +1
-1kgid =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.
Quoted 4 lines
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.
Quoted 4 lines
(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.
Quoted 3 lines
--Andy
Thanks.
Signature · 1 line
Chen Gang
Re: [PATCH 1/2] kernel/sys.c: return the current gid when error occurs
In reply to Andy LutomirskiQuoted 4 lines · Andy Lutomirski
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.
Quoted 2 lines
(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.
Re: [PATCH 1/2] kernel/sys.c: return the current gid when error occurs
Quoted 13 lines · Oleg Nesterov
Quoted 4 lines · Andy Lutomirski
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.
Quoted 7 lines
Quoted 2 lines
(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.)
Quoted 2 lines
And perhaps the man page should be changed. Add Michael.
Agreed. The text is a bit odd.
Quoted 3 lines
Oleg.
Signature · 2 lines
Andy Lutomirski AMA Capital Management, LLC
Re: [PATCH 1/2] kernel/sys.c: return the current gid when error occurs
Quoted 14 lines · Andy Lutomirski
Quoted 13 lines · Oleg Nesterov
Quoted 4 lines · Andy Lutomirski
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.
Quoted 8 lines
Quoted 7 lines
Quoted 2 lines
(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.
Quoted 10 lines
I suspect that changing this without introducing security or other bugs is impossible. If someone wanted to add
new_setfsuidthat returned an error when it failed, that would be a different story. (I'm not going to do that myself.)Quoted 2 lines
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"
Quoted 6 lines
Quoted 3 lines
Oleg.
Thanks.
Signature · 1 line
Chen Gang
Re: [PATCH 1/2] kernel/sys.c: return the current gid when error occurs
Quoted 26 lines · Chen Gang
Quoted 14 lines · Andy Lutomirski
Quoted 13 lines · Oleg Nesterov
Quoted 4 lines · Andy Lutomirski
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.Quoted 8 lines
Quoted 7 lines
Quoted 2 lines
(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.
Quoted 7 lines
Hmm... as a pair function, we need add
getfsuid()too, if we do not add it, it will make negative effect withsetfsuid().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
Re: [PATCH 1/2] kernel/sys.c: return the current gid when error occurs
Quoted 30 lines · Andy Lutomirski
Quoted 29 lines · Chen Gang
Quoted 14 lines · Andy Lutomirski
Quoted 13 lines · Oleg Nesterov
Quoted 4 lines · Andy Lutomirski
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.Quoted 8 lines
Quoted 7 lines
Quoted 2 lines
(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 withsetfsuid().
Quoted 7 lines
Quoted 4 lines
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()andsetfsuid2()?
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().
Quoted 3 lines
--Andy
Thanks.
Signature · 1 line
Chen Gang
Re: [PATCH 1/2] kernel/sys.c: return the current gid when error occurs
Quoted 39 lines · Chen Gang
Quoted 30 lines · Andy Lutomirski
Quoted 29 lines · Chen Gang
Quoted 14 lines · Andy Lutomirski
Quoted 13 lines · Oleg Nesterov
Quoted 4 lines · Andy Lutomirski
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.Quoted 8 lines
Quoted 7 lines
Quoted 2 lines
(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 withsetfsuid().Quoted 7 lines
Quoted 4 lines
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()andsetfsuid2()?
Quoted 8 lines
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 usegetfsuid2()to bypass the history complex.And 2nd reason:
getfsuid()seems more like the pair ofsetfsuid(), not forsetfsuid2().
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
Signature · 3 lines
Michael Kerrisk Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/ Author of "The Linux Programming Interface", http://blog.man7.org/
Re: [PATCH 1/2] kernel/sys.c: return the current gid when error occurs
Quoted 88 lines · Michael Kerrisk (man-pages)
Quoted 39 lines · Chen Gang
Quoted 30 lines · Andy Lutomirski
Quoted 29 lines · Chen Gang
Quoted 14 lines · Andy Lutomirski
Quoted 13 lines · Oleg Nesterov
Quoted 4 lines · Andy Lutomirski
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.Quoted 8 lines
Quoted 7 lines
Quoted 2 lines
(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 withsetfsuid().Quoted 7 lines
Quoted 4 lines
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()andsetfsuid2()?Quoted 8 lines
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 usegetfsuid2()to bypass the history complex.And 2nd reason:
getfsuid()seems more like the pair ofsetfsuid(), not forsetfsuid2().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.
Quoted 3 lines
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.
Quoted 5 lines
Cheers,
Michael
Thanks.
Signature · 1 line
Chen Gang
Re: [PATCH 1/2] kernel/sys.c: return the current gid when error occurs
In reply to Oleg NesterovQuoted 16 lines · Oleg Nesterov
Quoted 4 lines · Andy Lutomirski
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.Quoted 2 lines
(FWIW, this behavior is awful and is probably the cause of a security bug or three, since success and failure are indistinguishable.
Quoted 6 lines
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
man2/setfsuid.2 +12 -7
@@ -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
Re: [PATCH 1/2] kernel/sys.c: return the current gid when error occurs
Quoted 57 lines · Michael Kerrisk (man-pages)
Quoted 16 lines · Oleg Nesterov
Quoted 4 lines · Andy Lutomirski
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.Quoted 2 lines
(FWIW, this behavior is awful and is probably the cause of a security bug or three, since success and failure are indistinguishable.
Quoted 6 lines
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
man2/setfsuid.2 +5
-7@@ -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
man2/setfsuid.2 The glibc · line 113
Quoted 10 lines
man2/setfsuid.2 +7
-0+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.
Signature · 1 line
Chen Gang
Re: [PATCH 1/2] kernel/sys.c: return the current gid when error occurs
Quoted 63 lines · Chen Gang
Quoted 62 lines · Michael Kerrisk (man-pages)
Quoted 16 lines · Oleg Nesterov
Quoted 4 lines · Andy Lutomirski
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.Quoted 2 lines
(FWIW, this behavior is awful and is probably the cause of a security bug or three, since success and failure are indistinguishable.
Quoted 6 lines
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
man2/setfsuid.2 +11
-7@@ -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 ()
Quoted 8 lines
man2/setfsuid.2 The glibc · line 113
Quoted 5 lines
man2/setfsuid.2 +1
-0+changed the filesystem user ID. At the very least, .B EPERMIs it suitable to mention this API is obsoleted and unneeded in man page ? ;-)
Yes, that seems reasonable. Done.
Cheers,
Michael
PATCH 2/2 kernel/sys.c: remove useless variable 'old_fsgid' for setfsgid()
In reply to Chen GangRemove useless variable 'old_fsgid' to make code clearer for readers.
--- kernel/sys.c | 9 ++------- 1 files changed, 2 insertions(+), 7 deletions(-)
kernel/sys.c +2 -7
@@ -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; }/**
Signature · 1 line
1.7.7.6
Re: [PATCH 2/2] kernel/sys.c: remove useless variable 'old_fsgid' for setfsgid()
Quoted 24 lines · Chen Gang
Remove useless variable '
old_fsgid' to make code clearer for readers.Signed-off-by Chen Gang <[email protected]>--- kernel/sys.c | 9 ++------- 1 files changed, 2 insertions(+), 7 deletions(-)kernel/sys.c +0
-2@@ -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))
kernel/sys.c SYSCALL_DEFINE1(setfsgid, gid_t, gid) · line 788
Quoted 6 lines
kernel/sys.c +2
-1@@ -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.
Quoted 13 lines
kernel/sys.c +0
-4} }abort_creds (new);return gid; - -change_okay: -commit_creds (new); -return old_fsgid; }/**
Signature · 1 line
Chen Gang
kernel/sys.c: for setfsuid(), return the current uid when error occurs
In reply to Chen GangThey 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'.
--
kernel/sys.c | 14 ++++++-------- 1 files changed, 6 insertions(+), 8 deletions(-)
Re: kernel/sys.c: for setfsuid(), return the current uid when error occurs
Please skip it, sorry for bothering you with waste information.
Quoted 10 lines · Chen Gang
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 <[email protected]>--
kernel/sys.c | 14 ++++++-------- 1 files changed, 6 insertions(+), 8 deletions(-)
Signature · 1 line
Chen Gang
cover kernel/sys.c: for setfsuid(), return the current uid when error occurs
In reply to Chen GangThey 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'.
--
kernel/sys.c | 14 ++++++-------- 1 files changed, 6 insertions(+), 8 deletions(-)
PATCH 1/2 kernel/sys.c: return the current uid when error occurs
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.
--- kernel/sys.c | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-)
kernel/sys.c +3 -3
@@ -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);
Signature · 1 line
1.7.7.6
PATCH 2/2 kernel/sys.c: remove useless variable 'old_fsuid' for setfsuid()
In reply to Chen GangRemove useless variable 'old_fsuid' to make code clearer for readers.
--- kernel/sys.c | 14 ++++++-------- 1 files changed, 6 insertions(+), 8 deletions(-)
kernel/sys.c +6 -8
@@ -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; }/*
Signature · 1 line
1.7.7.6
Re: [PATCH 2/2] kernel/sys.c: remove useless variable 'old_fsuid' for setfsuid()
Quoted 12 lines · Chen Gang
Remove useless variable '
old_fsuid' to make code clearer for readers.Signed-off-by Chen Gang <[email protected]>--- kernel/sys.c | 14 ++++++-------- 1 files changed, 6 insertions(+), 8 deletions(-)kernel/sys.c +0
-0
kernel/sys.c SYSCALL_DEFINE1(setfsuid, uid_t, uid) · line 734
Quoted 9 lines
kernel/sys.c +0
-2@@ -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() ?
Quoted 4 lines
kernel/sys.c +0
-0kuid =make_kuid (old->user_ns, uid);if (!uid_valid (kuid))@@ -747,17 +745,17 @@ SYSCALL_DEFINE1(setfsuid, uid_t, uid) nsown_capable(CAP_SETUID)) {
kernel/sys.c SYSCALL_DEFINE1(setfsuid, uid_t, uid) · line 753
Quoted 10 lines
kernel/sys.c +6
-2if (!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() ?
Quoted 13 lines
kernel/sys.c +0
-4} }abort_creds (new);return uid; - -change_okay: -commit_creds (new); -return old_fsuid; }/*
Signature · 1 line
Chen Gang
PATCH 1/1 kernel/sys.c: improve the usage of return value
In reply to Chen GangImprove 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.
--- kernel/sys.c | 147 +++++++++++++++++++++++++++++++--------------------------- 1 files changed, 79 insertions(+), 68 deletions(-)
kernel/sys.c +79 -68
@@ -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 ; }/**
Signature · 1 line
1.7.7.6
Re: [PATCH] kernel/sys.c: improve the usage of return value
According to the related discussion in another thread, this patch can be obsoleted now.
Thanks.
Quoted 332 lines · Chen Gang
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(), andoverride_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 <[email protected]>--- kernel/sys.c | 147 +++++++++++++++++++++++++++++++--------------------------- 1 files changed, 79 insertions(+), 68 deletions(-)kernel/sys.c +79
-68@@ -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 ; }/**
Signature · 1 line
Chen Gang
Quoted 9 lines · Chen Gang
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 <[email protected]>--
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
Signature · 2 lines
Kees Cook Chrome OS Security
Quoted 11 lines · Kees Cook
Quoted 9 lines · Chen Gang
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 <[email protected]>--
kernel/sys.c | 15 +++++---------- 1 files changed, 5 insertions(+), 10 deletions(-)
Quoted 8 lines
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).
Quoted 4 lines
Thanks,
-Kees
Thanks.
Signature · 1 line
Chen Gang