Issues with seteuid()?
Hi all,
I'm the Debian package maintainer for Squid (HTTP Proxy). I received the forwarded bug report describing issues in seteuid() on palinux. While using seteuid(), forked processes terminate with SEGV.
Is it a known problem?
Thanks.
L
Please CC: me, I'm not subscribed to this list.
-----Forwarded Message-----
Quoted 18 lines
This small mail to mentionned that I reach to make squid operational on a linux-2.4.20-pa17 thanks to the following tips:
in debian rules replace statement
ac_cv_func_setresuid=no \ by ac_cv_func_setresuid=yes \so that function
leave_suid()[intosrc/tools.c] will usesetresuid()in place ofseteuid()before launchfork().Is it a know problem on palinux?
Greetings,
JoelPS: Luigi, I also test it on 2.5.1 and it works also for parisc linux (testing config). HTH
Signature · 2 lines
Luigi Gangitano -- <[email protected]> -- <[email protected]> GPG: 1024D/924C0C26: 12F8 9C03 89D3 DB4A 9972 C24A F19B A618 924C 0C26
Quoted 5 lines · Luigi Gangitano
I'm the Debian package maintainer for Squid (HTTP Proxy). I received the forwarded bug report describing issues in
seteuid()on palinux. While usingseteuid(), forked processes terminate with SEGV.Is it a known problem?
I wonder how it can be a problem at all. The kernel implements only sys_setresuid() and i would imagine that glibc implements both seteuid() and setresuid() in terms of this system call.
Perhaps someone who's willing to touch glibc would care to comment?
Signature · 3 lines
"It's not Hollywood. War is real, war is primarily not about defeat or victory, it is about death. I've seen thousands and thousands of dead bodies. Do you think I want to have an academic debate on this subject?" -- Robert Fisk
Quoted 5 lines
I wonder how it can be a problem at all. The kernel implements only
sys_setresuid()and i would imagine that glibc implements bothseteuid()andsetresuid()in terms of this system call.Perhaps someone who's willing to touch glibc would care to comment?
seteuid() works fine in simple tests. i don't think it's seteuid... something else is broken. can someone provide a simple test case for the segfault?
randolph
Signature · 3 lines
Randolph Chung Debian GNU/Linux Developer, hppa/ia64 ports http://www.tausq.org/
Hi Randolph,
As per your request, I do spent some time to compose this 'small' test case bases on simplified parts of squid:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
/* getpid(), geteuid() */
#include <sys/types.h>
#include <unistd.h>
/* setgroups() */
#include <grp.h>
/* mkdir() */
#include <sys/stat.h>
#define MAXPATHLEN 256
/* waitpid() */
#include <sys/wait.h>
char *effectiveUser="proxy";uid_t effectiveUserID=13;gid_t effectiveGroupID=13;
/* Define if you have the setgroups function. */
#define HAVE_SETGROUPS 1
/*
* Yay! Another Linux brokenness. Its not good enough to know that
* setresuid() exists, because RedHat 5.0 declare setresuid() but
* doesn't implement it.
*/
#define HAVE_SETRESUID 1
#undef HAVE_SETRESUID
/*
*/
/*
man setresuid NOTES:
Under HP-UX and FreeBSD the prototype is found in <unistd.h>.
Under
Linux there is so far no include file giving the prototype - this
is a
glibc bug. Programs using this system call must add the prototype
them-
selves.
*/
#ifdef HAVE_SETRESUID
/* because man setresuid mentionned it as a lake of linux? */ intsetresuid(uid_t ruid, uid_t euid, uid_t suid);
#endif
/* Define if you have the seteuid function. */
#define HAVE_SETEUID 1
/*
* xstrerror() - strerror() wrapper
*/
const char *
xstrerror(void)
{
static char xstrerror_buf[BUFSIZ];
static char strerror_buf[BUFSIZ];
snprintf(strerror_buf, BUFSIZ, "%s", strerror(errno));
if (strerror_buf)
snprintf(xstrerror_buf, BUFSIZ, "(%d) %s", errno, strerror_buf);
else
snprintf(xstrerror_buf, BUFSIZ, "(%d) Unknown", errno);
return xstrerror_buf;
}/* leave a privilegied section. (Give up any privilegies)
* Routines that need privilegies can rap themselves in enter_suid()
* and leave_suid()
* To give upp all posibilites to gain privilegies use no_suid() */
voidleave_suid(void)
{
fprintf(stderr, "leave_suid: PID %d called\n", (int) getpid());
if (geteuid() != 0)
return;
/* Started as a root, check suid option */
if (effectiveUser == NULL)
return;
#if HAVE_SETGROUPS
setgroups(1, &effectiveGroupID);#endif
if (setgid(effectiveGroupID) < 0)
fprintf(stderr, "ALERT: setgid: %s\n", xstrerror());
fprintf(stderr, "leave_suid: PID %d giving up root, becoming '%s'\n",
(int) getpid(), effectiveUser);
#if HAVE_SETRESUID
if (setresuid(effectiveUserID, effectiveUserID, 0) < 0)
fprintf(stderr, "ALERT: setresuid: %s\n", xstrerror());
#elif HAVE_SETEUID
if (seteuid(effectiveUserID) < 0)
fprintf(stderr, "ALERT: seteuid: %s\n", xstrerror());
#else
if (setuid(effectiveUserID) < 0)
fprintf(stderr, "ALERT: setuid: %s\n", xstrerror());
#endif
}
static void
setEffectiveUser(void)
{
leave_suid(); /* Run as non privilegied user */
if (geteuid() == 0) {
fprintf(stderr, "Squid is not safe to run as root! If you must\n");
fprintf(stderr, "start Squid as root, then you must configure\n");
fprintf(stderr, "it to run as a non-priveledged user with the\n");
fprintf(stderr, "'cache_effective_user' option in the config file.\n");
fprintf(stderr, "Don't run Squid as root, set 'cache_effective_user'!\n");
abort();
}
}static intstoreUfsDirCreateDirectory(const char *path)
{
int created = 0;
if (0 != mkdir(path, 0755)) {
fprintf(stderr, "Failed to make swai directory %s: %s\n",
path, xstrerror());
}
return created;
}static voidstoreUfsDirCreateSwapSubDirs(char * Path)
{
int i, k;
static char name[MAXPATHLEN];
for (i = 0; i < 16; i++) {
snprintf(name, MAXPATHLEN, "%s/%02X", Path, i);
storeUfsDirCreateDirectory(name);
fprintf(stderr, "Making directories in %s\n", name);
for (k = 0; k < 32; k++) {
snprintf(name, MAXPATHLEN, "%s/%02X/%02X", Path, i, k);
storeUfsDirCreateDirectory(name);
}
}
}static voidstoreUfsDirNewfs(char * Path)
{
fprintf(stderr, "Creating swap space in %s\n", Path);
storeUfsDirCreateSwapSubDirs(Path);
}void
storeCreateSwapDirectories(void)
{
int i;
pid_t pid;
int status;
for (i = 0; i < 1; i++) {
if (fork())
continue;
storeUfsDirNewfs("/var/spool/squid");
exit(0);
}
do {
pid = waitpid(-1, &status, 0);
} while (pid > 0 || (pid < 0 && errno == EINTR));
}intmain(int argc, char **argv)
{
/* only opt_create_swap_dirs */
setEffectiveUser();
fprintf(stderr, "Creating Swap Directories\n");
storeCreateSwapDirectories();
return 0;
}A. On a testing debian system (ie gcc-3.0 3.0.4-10 && libc6 2.2.5-14.3) and the very last kernel 2.4.20-pa23:
Compile with gcc -O 2 -Wall -D_REENTRANT foo.c -o foo
[ Create a user and a group named proxy with id 13 for both ]
First as it is ./foo would failled to fork() immediately with 'Segmentation fault'.
Secondly edit foo.c to comment out #undifined HAVE_SETRESUID; it would reach to fork without problem (eventhough it did not reach to create dir)
B. On an unstable debian (ie gcc-3.2 3.2.2-0pre6 && libc6 2.3.1-10) running the same kernel: this problem doesn't occure.
hth,
Joel
Quoted 14 lines
-- Original Message --
From: Randolph Chung <[email protected]>
To: Matthew Wilcox <[email protected]>
Cc: Luigi Gangitano <[email protected]>,
[email protected]
Subject: Re: [parisc-linux] Issues withseteuid()?
Reply-To: Randolph Chung <[email protected]>
Date: Sun, 12 Jan 2003 19:11:09 -0800Quoted 4 lines
I wonder how it can be a problem at all. The kernel implements only
sys_setresuid()and i would imagine that glibc implements bothseteuid()andsetresuid()in terms of this system call.
Quoted 15 lines
Quoted 1 line
Perhaps someone who's willing to touch glibc would care to comment?
seteuid()works fine in simple tests. i don't think it's seteuid... something else is broken. can someone provide a simple test case for the segfault?randolph
Signature · 7 lines
Randolph Chung Debian GNU/Linux Developer, hppa/ia64 ports http://www.tausq.org/ _______________________________________________ parisc-linux mailing list [email protected] http://lists.parisc-linux.org/mailman/listinfo/parisc-linux
*********************************************
Vous surfez toujours avec une ligne classique ?
Faites des economies avec Tiscali Complete...
Plus d'info sur ... http://complete.tiscali.be
Quoted 9 lines
A. On a testing debian system (ie gcc-3.0 3.0.4-10 && libc6 2.2.5-14.3) and the very last kernel 2.4.20-pa23:
Compile with gcc -O 2 -Wall -D_REENTRANT
foo.c-o foo[ Create a user and a group named proxy with id 13 for both ]
First as it is ./foo would failled to
fork()immediately with 'Segmentation fault'.
# uname -a Linux legolas 2.4.20-pa23 #110 Mon Jan 27 23:44:18 PST 2003 parisc unknown unknown GNU/Linux
ii gcc-3.0 3.0.4-7 The GNU C compiler. ii libc6 2.2.5-14.3 GNU C Library: Shared libraries and Timezone
# gcc-3.0 -O2 -Wall -D_REENTRANT seteuid.c -o seteuid # ./seteuid leave_suid: PID 18443 called leave_suid: PID 18443 giving up root, becoming 'proxy' Creating Swap Directories [....]
no segfault...
can you maybe run it with strace and send the last few lines of output?
randolph
Signature · 3 lines
Randolph Chung Debian GNU/Linux Developer, hppa/ia64 ports http://www.tausq.org/
Randolph,
Quoted 27 lines
Quoted 3 lines
A. On a testing debian system (ie gcc-3.0 3.0.4-10 && libc6 2.2.5-14.3)
and
Quoted 8 lines
the very last kernel 2.4.20-pa23:
Compile with gcc -O 2 -Wall -D_REENTRANT
foo.c-o foo[ Create a user and a group named proxy with id 13 for both ]
First as it is ./foo would failled to
fork()immediately with 'Segmentation fault'.# uname -a Linux legolas 2.4.20-pa23 #110 Mon Jan 27 23:44:18 PST 2003 parisc unknown unknown GNU/Linuxii gcc-3.0 3.0.4-7 The GNU C compiler. ii libc6 2.2.5-14.3 GNU C Library: Shared libraries and Timezone# gcc-3.0 -O2 -Wall -D_REENTRANT seteuid.c -o seteuid # ./seteuid leave_suid: PID 18443 called leave_suid: PID 18443 giving up root, becoming 'proxy' Creating Swap Directories [....]
Quoted 4 lines
no segfault...
can you maybe run it with strace and send the last few lines of output?
Well so short that I can give you all:
ii gcc-3.0 3.0.4-10 The GNU C compiler. ii gcc-3.0-base 3.0.4-10 The GNU Compiler Collection (base package). ii libc6 2.2.5-14.3 GNU C Library: Shared libraries and Timezone
# strace -f ./a.out
execve("./a.out", ["./a.out"], [/* 18 vars */]) = 0
newuname({sys="Linux", node="fw01.office.palinux", ...}) = 0
brk(0) = 0x26000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
= 0x40017000
open("/etc/ld.so.preload", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY) = 3
fstat64(3, {st_mode=0, st_size=0, ...}) = 0
mmap(NULL, 16726, PROT_READ, MAP_PRIVATE, 3, 0) = 0x40018000
close(3) = 0
open("/lib/libc.so.6", O_RDONLY) = 3
read(3, "\177ELF\1\2\1\3\0\0\0\0\0\0\0\0\0\3\0\17\0\0\0\1\0\2\37"..., 1024)
= 1024
fstat64(3, {st_mode=0, st_size=0, ...}) = 0
mmap(NULL, 1392404, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) = 0x40028000
mprotect(0x4015f000, 118548, PROT_NONE) = 0
mmap(0x4016e000, 45056, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_FIXED,
3, 0x136000) = 0x4016e000
mmap(0x40179000, 12052, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS,
-1, 0) = 0x40179000
close(3) = 0
munmap(0x40018000, 16726) = 0
getpid() = 25520
write(2, "leave_suid: PID 25520 called\n", 29leave_suid: PID 25520 called
) = 29
geteuid() = 0
setgroups(1, [13]) = 0
setgid(13) = 0
getpid() = 25520
write(2, "leave_suid: PID 25520 giving up "..., 55leave_suid: PID 25520 giving
up root, becoming 'proxy'
) = 55
setresuid(ruid 4294967295, euid 13, suid 4294967295) = 0
geteuid() = 13
write(2, "Creating Swap Directories\n", 26Creating Swap Directories
) = 26
fork() = -1 EAGAIN (Resource temporarily
unavailable)
--- SIGSEGV (Segmentation fault) ---
+++ killed by SIGSEGV +++Well as explained in a previous mail if I do a su - proxy and launch same program no problem to fork() ??
Thanks for your attention,
Joel
*********************************************
Vous surfez toujours avec une ligne classique ?
Faites des economies avec Tiscali Complete...
Plus d'info sur ... http://complete.tiscali.be
Hi all,
Here is a 'small' test case which reproduce the problem on a sarge (ie testing) debian (gcc-3.0_3.0.4-12; libc6_2.2.5-14.3) running very last kernel 2.4.20-pa23:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
/* getpid(), geteuid() */
#include <sys/types.h>
#include <unistd.h>
/* setgroups() */
#include <grp.h>
/* mkdir() */
#include <sys/stat.h>
#define MAXPATHLEN 256
/* waitpid() */
#include <sys/wait.h>
char *effectiveUser="proxy";uid_t effectiveUserID=13;gid_t effectiveGroupID=13;
/* Define if you have the setgroups function. */
#define HAVE_SETGROUPS 1
/*
* Yay! Another Linux brokenness. Its not good enough to know that
* setresuid() exists, because RedHat 5.0 declare setresuid() but
* doesn't implement it.
*/
#define HAVE_SETRESUID 1
#undef HAVE_SETRESUID
/*
*/
/*
man setresuid NOTES:
Under HP-UX and FreeBSD the prototype is found in <unistd.h>.
Under
Linux there is so far no include file giving the prototype - this
is a
glibc bug. Programs using this system call must add the prototype
them-
selves.
*/
#ifdef HAVE_SETRESUID
intsetresuid(uid_t ruid, uid_t euid, uid_t suid);
#endif
/* Define if you have the seteuid function. */
#define HAVE_SETEUID 1
/*
* xstrerror() - strerror() wrapper
*/
const char *
xstrerror(void)
{
static char xstrerror_buf[BUFSIZ];
static char strerror_buf[BUFSIZ];
snprintf(strerror_buf, BUFSIZ, "%s", strerror(errno));
if (strerror_buf)
snprintf(xstrerror_buf, BUFSIZ, "(%d) %s", errno, strerror_buf);
else
snprintf(xstrerror_buf, BUFSIZ, "(%d) Unknown", errno);
return xstrerror_buf;
}/* leave a privilegied section. (Give up any privilegies)
* Routines that need privilegies can rap themselves in enter_suid()
* and leave_suid()
* To give upp all posibilites to gain privilegies use no_suid() */
voidleave_suid(void)
{
fprintf(stderr, "leave_suid: PID %d called\n", (int) getpid());
if (geteuid() != 0)
return;
/* Started as a root, check suid option */
if (effectiveUser == NULL)
return;
#if HAVE_SETGROUPS
setgroups(1, &effectiveGroupID);#endif
if (setgid(effectiveGroupID) < 0)
fprintf(stderr, "ALERT: setgid: %s\n", xstrerror());
fprintf(stderr, "leave_suid: PID %d giving up root, becoming '%s'\n",
(int) getpid(), effectiveUser);
#if HAVE_SETRESUID
if (setresuid(effectiveUserID, effectiveUserID, 0) < 0)
fprintf(stderr, "ALERT: setresuid: %s\n", xstrerror());
#elif HAVE_SETEUID
if (seteuid(effectiveUserID) < 0)
fprintf(stderr, "ALERT: seteuid: %s\n", xstrerror());
#else
if (setuid(effectiveUserID) < 0)
fprintf(stderr, "ALERT: setuid: %s\n", xstrerror());
#endif
}
static void
setEffectiveUser(void)
{
leave_suid(); /* Run as non privilegied user */
if (geteuid() == 0) {
fprintf(stderr, "Squid is not safe to run as root! If you must\n");
fprintf(stderr, "start Squid as root, then you must configure\n");
fprintf(stderr, "it to run as a non-priveledged user with the\n");
fprintf(stderr, "'cache_effective_user' option in the config file.\n");
fprintf(stderr, "Don't run Squid as root, set 'cache_effective_user'!\n");
abort();
}
}static intstoreUfsDirCreateDirectory(const char *path)
{
int created = 0;
if (0 != mkdir(path, 0755)) {
fprintf(stderr, "Failed to make swai directory %s: %s\n",
path, xstrerror());
}
return created;
}static voidstoreUfsDirCreateSwapSubDirs(char * Path)
{
int i, k;
static char name[MAXPATHLEN];
for (i = 0; i < 16; i++) {
snprintf(name, MAXPATHLEN, "%s/%02X", Path, i);
storeUfsDirCreateDirectory(name);
fprintf(stderr, "Making directories in %s\n", name);
for (k = 0; k < 32; k++) {
snprintf(name, MAXPATHLEN, "%s/%02X/%02X", Path, i, k);
storeUfsDirCreateDirectory(name);
}
}
}static voidstoreUfsDirNewfs(char * Path)
{
fprintf(stderr, "Creating swap space in %s\n", Path);
storeUfsDirCreateSwapSubDirs(Path);
}void
storeCreateSwapDirectories(void)
{
int i;
pid_t pid;
int status;
for (i = 0; i < 1; i++) {
if (fork())
continue;
storeUfsDirNewfs("/var/spool/squid");
exit(0);
}
do {
pid = waitpid(-1, &status, 0);
} while (pid > 0 || (pid < 0 && errno == EINTR));
}intmain(int argc, char **argv)
{
/* only opt_create_swap_dirs */
setEffectiveUser();
fprintf(stderr, "Creating Swap Directories\n");
storeCreateSwapDirectories();
return 0;
}(rebuild from simplified parts of squid-2.5 src)
compile with: gcc -O 2 -Wall -D_REENTRANT file.c -o ct
[create a user and a group named proxy with id 13 both]
compile as it is it, it will failled immediately with 'Segmentation fault'
edit sources to comment out '#undef HAVE_SETRESUID' line, recompile with same option and it would fork without problem (even thought it will failled to actually create dir)
hth,
Joel
PS: this test case doesn't present the same pb on an unstable debian (ie compile with gcc-3.2_3.2.2-0pre6 & libc6_2.3.1-10). I try this on the same kernel running each the two different install.
Quoted 15 lines
-- Original Message --
From: Luigi Gangitano <[email protected]>
To: [email protected]
Subject: [parisc-linux] Issues withseteuid()?
Date: 12 Jan 2003 16:49:29 +0100Hi all,
I'm the Debian package maintainer for Squid (HTTP Proxy). I received the forwarded bug report describing issues inseteuid()on palinux. While usingseteuid(), forked processes terminate with SEGV.Is it a known problem?
Quoted 16 lines
Thanks.
L
Please CC: me, I'm not subscribed to this list.
-----Forwarded Message-----
Quoted 9 lines
This small mail to mentionned that I reach to make squid operational on a linux-2.4.20-pa17 thanks to the following tips:
in debian rules replace statement
ac_cv_func_setresuid=no \ by ac_cv_func_setresuid=yes \so that function
leave_suid()[intosrc/tools.c] will usesetresuid()
in
Quoted 8 lines
Quoted 8 lines
place of
seteuid()before launchfork().Is it a know problem on palinux?
Greetings,
JoelPS: Luigi, I also test it on 2.5.1 and it works also for parisc linux
(testing
Quoted 8 lines
Quoted 1 line
config). HTH
Signature · 4 lines
Luigi Gangitano -- <[email protected]> -- <[email protected]> GPG: 1024D/924C0C26: 12F8 9C03 89D3 DB4A 9972 C24A F19B A618 924C 0C26 Attachment: signature.asc
*********************************************
Vous surfez toujours avec une ligne classique ?
Faites des economies avec Tiscali Complete...
Plus d'info sur ... http://complete.tiscali.be