public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Hao Chen <hchen@cs.berkeley.edu>
To: linux-kernel@vger.kernel.org
Cc: David Wagner <daw@cs.berkeley.edu>,
	ddean@csl.sri.com, Hao Chen <hchen@eecs.berkeley.edu>
Subject: A security bug w.r.t. fsuid?
Date: Fri, 26 Apr 2002 12:25:50 -0700	[thread overview]
Message-ID: <3CC9A9BE.7030606@cs.berkeley.edu> (raw)

We came across a possible security bug with regard to fsuid while doing
research on Linux's user ID model.  In linux/kernel/sys.c, in the comment
just before the body of cap_emulate_setxuid(), it says:

   *  fsuid is handled elsewhere. fsuid == 0 and {r,e,s}uid!= 0 should
   *  never happen.

However, the following program shows that a process can enter the state
where ruid=euid=suid!=0 and fsuid=0.  The problem is with setresuid().
While setuid() and setreuid() always set fsuid to euid, setresuid(ruid,
euid, suid) fails to do the same when the euid parameter is -1.

Normally, a programmer expects that if none of the ruid, euid, and suid of a
process is zero, the process has no root privileges.  This seems to be the
reason behind the above comment from linux/kernel/sys.c.  If this invariant
is not satisfied, i.e. if a process can get ruid=euid=suid!=0 and fsuid=0, 
an unwary programmer may allow the process to create a file whose data are
supplied by an untrusted user.  Since fsuid=0, the file will be owned by
root.   If the file happens to be setuid-root, then the user can gain root
access (by asking the process to write shell command into the file and then
running the file).

We are not sure if this invariant is a true invariant or just a 
documentation error, and how much kernel code rely on this invariant.  Could 
anyone point out?

Thanks,

- Hao


Run the following program as user root
-------------------------------------------------------
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>

int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid);
int setresuid(uid_t ruid, uid_t euid, uid_t suid);
int setfsuid(uid_t);

int getfsuid(uid_t *fsuid)
{
    pid_t pid;
    char filename[1024], str[1024], *str2;
    FILE *fp;
    int i;

    if ((pid = getpid()) < 0)
    {
      perror("getpid()");
      exit(1);
    }
    sprintf(filename, "/proc/%u/status", pid);
    if ((fp = fopen(filename, "r")) == NULL)
    {
      perror("fopen()");
      exit(1);
    }
    while (fgets(str, 1023, fp) != NULL)
    {
      if ((str2 = strstr(str, "Uid:")) == str)
      {
        strtok(str, "\t");
        for (i = 0; i < 4; i++)
          str2 = strtok(NULL, "\t");
        *fsuid = atoi(str2);
        fclose(fp);
        return 0;
      }
    }

    return -1;
}

int main()
{
    uid_t alice = 100;
    uid_t ruid, euid, suid, fsuid;

    // Now ruid==0, euid==0, suid==0, fsuid==0
    if (setresuid(alice, alice, -1) < 0)
    {
      perror("setresuid");
      exit(1);
    }
    // Now ruid==alice, euid==alice, suid==0, fsuid==alice
    setfsuid(0);
    // Now ruid==alice, euid==alice, suid==0, fsuid==0
    if (setresuid(-1, -1, alice) < 0)
    {
      perror("setresuid");
      exit(1);
    }
    // Now ruid==alice, euid==alice, suid==alice, fsuid==0
    // But according to linux/kernel/sys.c:
    // "fsuid == 0 and {r,e,s}uid!= 0 should never happen."
    if (getresuid(&ruid, &euid, &suid) < 0)
    {
      perror("getresuid");
      exit(1);
    }
    if (getfsuid(&fsuid) < 0)
    {
      fprintf(stderr, "getfsuid failed\n");
    }
    printf("ruid=%u  euid=%u  suid=%d  fsuid=%d\n", ruid, euid, suid, fsuid);
}



                 reply	other threads:[~2002-04-26 19:25 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=3CC9A9BE.7030606@cs.berkeley.edu \
    --to=hchen@cs.berkeley.edu \
    --cc=daw@cs.berkeley.edu \
    --cc=ddean@csl.sri.com \
    --cc=hchen@eecs.berkeley.edu \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox