public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [2.6.29-rc2 regression] CRED changes causing setuid failures
@ 2009-01-29 21:35 David Smith
  0 siblings, 0 replies; only message in thread
From: David Smith @ 2009-01-29 21:35 UTC (permalink / raw)
  To: linux-kernel
  Cc: Roland McGrath, Frank Ch. Eigler, David Howells, Oleg Nesterov

[-- Attachment #1: Type: text/plain, Size: 794 bytes --]

I'm seeing setuid problems with 2.6.29-rc2.  I've narrowed the problem
down to the 2 attached test files.  test1, a setuid root program drops
root euid (by calling setresuid()), then execs test2 (a non-setuid
program).  Test2 then execs test1, but test1's euid isn't set back to 0
as it should be.

After doing a git bisect, here's the change that causes the problem:

commit d84f4f992cbd76e8f39c488cf0c5d123843923b1
Author: David Howells <dhowells@redhat.com>
Date:   Fri Nov 14 10:39:23 2008 +1100

    CRED: Inaugurate COW credentials

I believe this regression is tied to the fact that test2 creates a 2nd
thread (that does nothing).  Without the 2nd thread, the test runs
correctly.

-- 
David Smith
dsmith@redhat.com
Red Hat
http://www.redhat.com
256.217.0141 (direct)
256.837.0057 (fax)

[-- Attachment #2: test1.c --]
[-- Type: text/x-csrc, Size: 1450 bytes --]

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <string.h>
#include <stdint.h>
#include <signal.h>
#include <errno.h>
#include <sys/wait.h>

int delete_mod = 0;

static int run_as(uid_t uid, gid_t gid, const char *path, char *const argv[])
{
    int i = 0;
    fprintf(stderr, "execing: ");
    while (argv[i]) {
	fprintf(stderr, "%s ", argv[i]);
	i++;
    }
    fprintf(stderr, "\n");

    /* Make sure we run as the full user.  If we're
     * switching to a non-root user, this won't allow
     * that process to switch back to root (since the
     * original process is setuid). */
    if (setresgid (gid, gid, gid) < 0) {
	perror("setresgid");
	exit(1);
    }
    if (setresuid (uid, uid, uid) < 0) {
	perror("setresuid");
	exit(1);
    }

    /* Actually run the command. */
    if (execv(path, argv) < 0)
	perror(path);
    _exit(1);
    return -1;
}


int main(int argc, char **argv)
{
    char *prog = argv[0];
    char *newargv[2];

    if (argc > 1)
	delete_mod = 1;

    fprintf(stderr, "%s: uid = %d, euid = %d\n", prog, (int)getuid(),
	    (int)geteuid());
    if (geteuid() != 0) {
	fprintf(stderr, "%s: ERROR - The effective user ID isn't root!\n",
		prog);
	exit(1);
    }

    if (delete_mod)
	exit(0);

    newargv[0] = "./test2";
    newargv[1] = NULL;
    if (run_as (getuid(), getgid(), newargv[0], newargv) < 0) {
	perror(argv[0]);
	return 1;
    }
    return 0;
}

[-- Attachment #3: test2.c --]
[-- Type: text/x-csrc, Size: 1545 bytes --]

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <string.h>
#include <stdint.h>
#include <signal.h>
#include <errno.h>
#include <pthread.h>
#include <sys/wait.h>

static void *thread_func(void *arg __attribute__ ((unused)))
{
    while (1) {
	/* do nothing */
    }
    return NULL;
}

static void setup_main_signals(void)
{
    pthread_t tid;
    struct sigaction sa;
    sigset_t *s = malloc(sizeof(*s));
    if (!s) {
	perror("malloc");
	exit(1);
    }
    sigfillset(s);
    pthread_sigmask(SIG_SETMASK, s, NULL);

    memset(&sa, 0, sizeof(sa));
    sigfillset(&sa.sa_mask);
    sa.sa_handler = SIG_IGN;
    sigaction(SIGINT, &sa, NULL);
    sigaction(SIGTERM, &sa, NULL);
    sigaction(SIGHUP, &sa, NULL);
    sigaction(SIGQUIT, &sa, NULL);

    sigemptyset(s);
    sigaddset(s, SIGINT);
    sigaddset(s, SIGTERM);
    sigaddset(s, SIGHUP);
    sigaddset(s, SIGQUIT);
    pthread_sigmask(SIG_SETMASK, s, NULL);
    if (pthread_create(&tid, NULL, thread_func, s) < 0) {
	perror("pthread_create");
	exit(1);
    }
}

void cleanup_and_exit(void)
{
    const char *test1 = "./test1";
    fprintf(stderr, "cleanup and exit\n");
    if (execlp(test1, basename (test1), "-d", NULL) < 0) {
	perror(test1);
	_exit(1);
    }
    _exit(0);
}

int main(int argc __attribute__ ((unused)), char **argv)
{
    char *prog = argv[0];

    fprintf(stderr, "%s: uid = %d, euid = %d\n", prog, (int)getuid(),
	    (int)geteuid());

    setup_main_signals();

    cleanup_and_exit();
    return 0;
}

[-- Attachment #4: Makefile --]
[-- Type: text/plain, Size: 249 bytes --]

CFLAGS = -D_GNU_SOURCE -Wall -Werror -Wunused
all: test1 test2

test1: test1.c
	gcc $(CFLAGS) -o test1 test1.c
	sudo chown root.root test1
	sudo chmod +s test1

test2: test2.c
	gcc $(CFLAGS) -o test2 test2.c -lpthread

clean:
	rm -f *.o test1 test2

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2009-01-29 21:35 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-01-29 21:35 [2.6.29-rc2 regression] CRED changes causing setuid failures David Smith

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox