Skip to contentSkip to conversation

setregid02, setresuid03: inval_user fix

PATCH In review Stanislav Kholmanskikh 2 participants 5 messages Jan 13, 2014 – Jan 14, 2014 2 messages not in the archive Library code

lore
Share & tools
lore
#3 lore raw

PATCH 2/2 setregid02, setresuid03: inval_user fix

In reply to a message not in the archive

Since there is no guarantee that (USHRT_MAX - 2) uid/gid is free on the platform it would be better to use special functions:

* tst_get_unused_uid
* tst_get_unused_gid

wrapped for 16-bit compatibility: if on the host there is no free uid/gid in between [0; 0xFFFE] the 16-bit test case should return TBROK.

---
 testcases/kernel/syscalls/setregid/setregid02.c   |    6 +++++-
 testcases/kernel/syscalls/setresuid/setresuid03.c |    8 +++++++-
 testcases/kernel/syscalls/utils/compat_gid.h      |   20 ++++++++++++++++++++
 testcases/kernel/syscalls/utils/compat_uid.h      |   20 ++++++++++++++++++++
 4 files changed, 52 insertions(+), 2 deletions(-)
testcases/kernel/syscalls/setregid/setregid02.c +5 -1
index ccbaa3e..a730a5e 100644
@@ -39,7 +39,7 @@ TCID_DEFINE(setregid02);
 
 static gid_t neg_one = -1;
 
-static gid_t inval_user = USHRT_MAX - 2;
+static gid_t inval_user;
 static struct passwd *ltpuser;
 
 static struct group nobody, root, bin;
@@ -177,6 +177,10 @@ static void setup(void)
 	GET_GID(nobody);
 	GET_GID(bin);
 
+	inval_user = GET_UNUSED_GID();
+	if (inval_user == -1)
+		tst_brkm(TBROK, NULL, "No free gid found");
+
 	TEST_PAUSE;
 }
 
testcases/kernel/syscalls/setresuid/setresuid03.c +7 -1
index 9bb0abd..085ed7b 100644
@@ -70,10 +70,12 @@
 #include <errno.h>
 #include <sys/wait.h>
 
+#include <compat_16.h>
+
 char *TCID = "setresuid03";
 
 uid_t neg_one = -1;
-uid_t inval_user = (USHRT_MAX - 2);
+uid_t inval_user;
 
 /* flag to tell parent if child passed or failed. */
 int flag = 0;
@@ -232,6 +234,10 @@ void setup(void)
 	bin = *(getpwnam("bin"));
 	bin_pw_uid = bin.pw_uid;
 
+	inval_user = GET_UNUSED_UID();
+	if (inval_user == -1)
+		tst_brkm(TBROK, NULL, "No free uid found");
+
 	/* Pause if that option was specified
 	 * TEST_PAUSE contains the code to fork the test with the -i option.
 	 * You want to make sure you do this before you create your temporary
testcases/kernel/syscalls/utils/compat_gid.h +20 -0
index 82f8d84..1ce713b 100644
@@ -48,4 +48,24 @@ GID_SIZE_CHECK(gid_t gid)
 
 #endif
 
+/* for 16-bit syscalls testing we can only
+ * use gids <= 0xFFFE */
+gid_t GET_UNUSED_GID(void)
+{
+	gid_t r;
+	r = tst_get_unused_gid();
+
+#ifdef TST_USE_COMPAT16_SYSCALL
+	if (!GID_SIZE_CHECK(r))
+		return -1;
+
+	/* kernel low2highgid() converts
+	 * 0xFFFF to (gid_t)-1 */
+	if (r == (GID_T)-1)
+		return -1;
+#endif
+
+	return r;
+}
+
 #endif /* __SETGID_COMPAT_16_H__ */
testcases/kernel/syscalls/utils/compat_uid.h +20 -0
index 8200698..68896f4 100644
@@ -48,4 +48,24 @@ UID_SIZE_CHECK(uid_t uid)
 
 #endif
 
+/* for 16-bit syscalls testing we can only
+ * use uids <= 0xFFFE */
+uid_t GET_UNUSED_UID(void)
+{
+	uid_t r;
+	r = tst_get_unused_uid();
+
+#ifdef TST_USE_COMPAT16_SYSCALL
+	if (!UID_SIZE_CHECK(r))
+		return -1;
+
+	/* kernel low2highuid() converts
+	 * 0xFFFF to (uid_t)-1 */
+	if (r == (UID_T)-1)
+		return -1;
+#endif
+
+	return r;
+}
+
 #endif /* __SETUID_COMPAT_16_H__ */
Signature · 13 lines
1.7.1


------------------------------------------------------------------------------
CenturyLink Cloud: The Leader in Enterprise Cloud Services.
Learn Why More Businesses Are Choosing CenturyLink Cloud For
Critical Workloads, Development Environments & Everything In Between.
Get a Quote or Start a Free Trial Today. 
http://pubads.g.doubleclick.net/gampad/clk?id=119420431&iu=/4140/ostg.clktrk
_______________________________________________
Ltp-list mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ltp-list
#1 lore raw

PATCH 1/2 lib: tst_get_unused_uid, tst_get_unused_gid

In reply to a message not in the archive

Implemented functions which return the first unused uid and gid.

---
 include/test.h    |    7 ++++
 lib/tst_uid_gid.c |   86 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 93 insertions(+), 0 deletions(-)
 create mode 100644 lib/tst_uid_gid.c
include/test.h +7 -0
index ffc1c8c..9f4cfd7 100644
@@ -264,6 +264,13 @@ void tst_mkfs(void (cleanup_fn)(void), const char *dev,
  */
 int tst_fill_file(const char *path, char pattern, size_t bs, size_t bcount);
 
+/* lib/tst_uid_gid.c
+ *
+ * Return the first unused uid and gid
+ */
+uid_t tst_get_unused_uid(void);
+gid_t tst_get_unused_gid(void);
+
 #ifdef TST_USE_COMPAT16_SYSCALL
 #define TCID_BIT_SUFFIX "_16"
 #elif  TST_USE_NEWER64_SYSCALL
lib/tst_uid_gid.c new file +86 -0

86 lines not on this page · raw message

Signature · 13 lines
1.7.1


------------------------------------------------------------------------------
CenturyLink Cloud: The Leader in Enterprise Cloud Services.
Learn Why More Businesses Are Choosing CenturyLink Cloud For
Critical Workloads, Development Environments & Everything In Between.
Get a Quote or Start a Free Trial Today. 
http://pubads.g.doubleclick.net/gampad/clk?id=119420431&iu=/4140/ostg.clktrk
_______________________________________________
Ltp-list mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ltp-list
#2 lore raw

Re: [LTP] [PATCH 1/2] lib: tst_get_unused_uid, tst_get_unused_gid

Hi!

Quoted 22 lines
lib/tst_uid_gid.c new file +21 -0
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2013 Oracle and/or its affiliates. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write the Free Software Foundation,
+ * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <grp.h>
+#include <limits.h>
+#include <pwd.h>

lib/tst_uid_gid.c line 31

Quoted 10 lines
lib/tst_uid_gid.c new file +10 -0
+#include <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+uid_t tst_get_unused_uid(void)
+{
+	struct passwd pwd;
+	struct passwd *result;
+	char *buf;
+	size_t bufsize;

I've changed the bufsize to long, because size_t is unsigned.

Side note: I wonder why ltp has only -Wall and not -Wall -W which prints warnings when signed and unsigned types are compared...

Quoted 4 lines
lib/tst_uid_gid.c new file +4 -0
+	int s;
+	uid_t uid;
+
+	bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);

lib/tst_uid_gid.c line 45

Quoted 10 lines
lib/tst_uid_gid.c new file +10 -0
+	if (bufsize == -1)
+		bufsize = 16384;
+
+	buf = malloc(bufsize);
+	if (buf == NULL)
+		return -1;
+
+	for (uid = 0; uid <= UINT_MAX - 1; uid++) {
+		s = getpwuid_r(uid, &pwd, buf, bufsize, &result);
+		if (result == NULL) {

I've added a free(buf) here otherwise we will leak memory.

lib/tst_uid_gid.c line 55

Quoted 10 lines
lib/tst_uid_gid.c new file +10 -0
+			if (s == 0)
+				return uid;
+			else
+				return -1;
+		}
+	}
+
+	free(buf);
+	return -1;
+}

And the same for the second one.

Signature · 13 lines
Cyril Hrubis
[email protected]

------------------------------------------------------------------------------
CenturyLink Cloud: The Leader in Enterprise Cloud Services.
Learn Why More Businesses Are Choosing CenturyLink Cloud For
Critical Workloads, Development Environments & Everything In Between.
Get a Quote or Start a Free Trial Today. 
http://pubads.g.doubleclick.net/gampad/clk?id=119420431&iu=/4140/ostg.clktrk
_______________________________________________
Ltp-list mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ltp-list
#4 lore raw
In reply to Stanislav Kholmanskikh

Hi!

Quoted 19 lines
testcases/kernel/syscalls/setresuid/setresuid03.c +3 -1
index 9bb0abd..085ed7b 100644
@@ -70,10 +70,12 @@
 #include <errno.h>
 #include <sys/wait.h>
 
+#include <compat_16.h>
+
 char *TCID = "setresuid03";
 
 uid_t neg_one = -1;
-uid_t inval_user = (USHRT_MAX - 2);
+uid_t inval_user;
 
 /* flag to tell parent if child passed or failed. */
 int flag = 0;

testcases/kernel/syscalls/setresuid/setresuid03.c void setup(void) · line 243

Quoted 10 lines
testcases/kernel/syscalls/setresuid/setresuid03.c +4 -0
@@ -232,6 +234,10 @@ void setup(void)
 	bin = *(getpwnam("bin"));
 	bin_pw_uid = bin.pw_uid;
 
+	inval_user = GET_UNUSED_UID();
+	if (inval_user == -1)
+		tst_brkm(TBROK, NULL, "No free uid found");
+
 	/* Pause if that option was specified
 	 * TEST_PAUSE contains the code to fork the test with the -i option.
 	 * You want to make sure you do this before you create your temporary

Hmm, the setresuid03 did not fail because the EPERM check kicks in even before the check for correct uid/gid. Which should probably be fixed because there does not seem to be a setresuid test for invalid values that would actually excercise such checks, but that can be fixed after the release.

Thanks for the patches, I will commit them right after packages are build and I have tested that everything is fine.

Signature · 13 lines
Cyril Hrubis
[email protected]

------------------------------------------------------------------------------
CenturyLink Cloud: The Leader in Enterprise Cloud Services.
Learn Why More Businesses Are Choosing CenturyLink Cloud For
Critical Workloads, Development Environments & Everything In Between.
Get a Quote or Start a Free Trial Today. 
http://pubads.g.doubleclick.net/gampad/clk?id=119420431&iu=/4140/ostg.clktrk
_______________________________________________
Ltp-list mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ltp-list
#6 lore raw
In reply to a message not in the archive

Hi!

Quoted 16 lines
Quoted 5 lines

Hmm, the setresuid03 did not fail because the EPERM check kicks in even before the check for correct uid/gid. Which should probably be fixed because there does not seem to be a setresuid test for invalid values that would actually excercise such checks, but that can be fixed after the release.

Hmm. I took a brief look at setregid() and setresuid() syscalls sources. And it seems that the only thing they care about is not "validity" or "invalidity" of uid/gid. It's the process permission (capabilities).

Given enough permission we can change real, effective or saved uid values with setresuid() to arbitrary values. If we don't have such permission we can change our uids only to the one of the current real, effective or saved uid values, in the other case we will receive EPERM. Actually, man setresuid states that :-[

Quoted 3 lines

setresuid() may return EINVAL, but I don't think we can raise it by passing an unused uid value to setresuid() (if we have permission setresuid() returns 0 if we don't - it returns EPERM).

I was under an impression that there are some checks (possibly in libc) because the test comments talks about invalid uids and gids, but thinking about it this behavior makes more sense (and checking both kernel source and libc source indeed proves this). Sorry for the confusion.

Note that the uid_valid() and gid_valid() checks are defined in include/linux/uidgid.h and can fail only if the value is ((kgid_t)-1) so as far as I can see the EINVAL cannot be triggered at all. And the same goes for uid.

Quoted 12 lines

So it's not bad that we are introducing tst_get_unused_uid, tst_get_unused_gid functions and setting inval_user in a more formal way. But It looks like passing inval_user value is the same as passing any other uid != real|effective|saved uid of the current process....

Since we have in setresuid03 a full set for nobody uid:

	setresuid(nobody, -1, -1)
	setresuid(-1, -1, nobody)
	setresuid(-1, nobody, -1)

what do you think about adding setresuid(inval_user, -1, -1) to the test case? Just in case...

Quoted 7 lines

Related to setregid02.
Even that test_data contains EINVAL for the last two members, setregid() doesn't return EINVAL for them. It returns EPERM for all the test cases.

You said that on SUSE setregid02 fails. I added a group with 65533 gid and executed setregid02 (current git version) and it passed. Could you check it again in your environment?

I looked again at setregid02 it sets it's uid and gid (actually all of them because it uses setuid() and setgid() as a root) to nobody's uid and gid before the test starts and by a coincidence these are set to 65534 and 65533 on SUSE. Which explains the failure.

The setresuid03 uses bin user instead.

Now let's keep the code as it is for the release, it works good enough and fix these a better way after it. One of the options is to set all three uids/gids to known values and loop on all possible uids/gids and expect EPERM on everything but the ones we set previously.

Signature · 13 lines
Cyril Hrubis
[email protected]

------------------------------------------------------------------------------
CenturyLink Cloud: The Leader in Enterprise Cloud Services.
Learn Why More Businesses Are Choosing CenturyLink Cloud For
Critical Workloads, Development Environments & Everything In Between.
Get a Quote or Start a Free Trial Today. 
http://pubads.g.doubleclick.net/gampad/clk?id=119420431&iu=/4140/ostg.clktrk
_______________________________________________
Ltp-list mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ltp-list