lkml.org 
[lkml]   [1999]   [Apr]   [4]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
Date
From
SubjectBUG? in sys_access() in Linux 2.2.x when euid!=0 and ruid==0

Hi,

Is this a minor bug or feature ?

access(fnm,mask) returns EACCES when euid!=0 and ruid==0 if
mask contains R_OK, W_OK or X_OK.

Why fs/open.c:sys_access() denies access for root in kernels
2.2.x ? I use attached test program. My patch is:

fs/open.c:sys_access.c():

if (current->uid)
cap_clear(current->cap_effective);

must be changed to:

if (current->uid)
cap_clear(current->cap_effective);
else
current->cap_effective = current->cap_permitted;


/* Symptom: */
/* in Linux-2.2.1 - 5 access() fails with EACCES for user root */
/* when EUID!=0 and RUID==0. current->cap_effective */
/* is 0 and must be loaded with current->cap_permitted */
/* before permission checks */
/* */
/* Patch for Linux 2.2.x: */
/* */
/* fs/open.c, sys_access(): */
/* */
/* if (current->uid) */
/* cap_clear(current->cap_effective); */
/* */
/* must be changed to (TESTED): */
/* */
/* if (current->uid) */
/* cap_clear(current->cap_effective); */
/* else */
/* current->cap_effective = current->cap_permitted; */
/* */
/* Tests: */
/* 2.0.35 OK */
/* 2.0.36 OK */
/* 2.1.* Not tested, may be when cap_* are added in the kernel */
/* 2.2.1 FAILED(BUG?) */
/* 2.2.2 FAILED(BUG?) */
/* 2.2.3 FAILED(BUG?) */
/* 2.2.4 FAILED(BUG?) */
/* 2.2.5 FAILED(BUG?) */
/* Other unices OK */
/************************************************************************/

/* Next is the test program */
/* test_access.c, J. Anastasov */
/* Test if access() returns EACCES for root in seteuid program, i.e. */
/* when euid != 0 and ruid == 0 */
/* */
/* Usage: */
/* gcc -o test_access test_access.c */
/* ./test_access */


#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>

/* Usage: test_access file */

/* USER_ID: any UID!=0 */
#define USER_ID 99
/* INVALID_GID: root must not be member of group with GID=INVALID_GID */
#define INVALID_GID 4321

int test(char *fnm,int mask)
{
int rc;

rc = access(fnm,mask);
if (rc < 0) {
if (EACCES == errno) {
printf("access(%s,%d): %s, THIS IS A BUG\n",fnm,mask,strerror(errno));
} else {
perror("access()");
}
} else {
printf("access(%s,%d): OK\n",fnm,mask);
}
return rc;
}
int main(int argc,char *argv[])
{
int rc;
FILE *fp;
char tmp[80];
char *fnm;

if (getuid() || geteuid()) {
printf("This program must be started as root\n");
return 1;
}
if (argc > 1) {
fnm = argv[1];
} else {
fnm = argv[0];
}
/* Set ownership: UID!=0 and GID!=0 */
rc = chown(fnm,USER_ID,INVALID_GID);
if (rc < 0) {
perror("chown()");
return 1;
}
/* Grant access for USER_ID:INVALID_GID, none for others */
rc = chmod(fnm,0550);
if (rc < 0) {
perror("chmod()");
return 1;
}
/* Change EUID only */
rc = seteuid(USER_ID);
if (rc < 0) {
perror("seteuid()");
return 1;
}
printf("EUID=%d, RUID=%d\n",(int)geteuid(),(int)getuid());
#ifdef __linux__
/* grep for "Cap" in /proc/self/status */
fp = fopen("/proc/self/status","r");
if (fp) {
while (fgets(tmp,sizeof(tmp)-1,fp)) {
if (!strncasecmp(tmp,"Cap",3)) {
printf("%s",tmp);
}
}
fclose(fp);
}
#endif
/* Here EUID=USER_ID, RUID=0 */
/* cap_effective is cleared and */
/* cap_permitted are not changed (RUID=0) by */
/* seteuid(USER_ID) */
/* Now check with access() while RUID=0 */
/* We expect full access for root */
rc = 0;
rc += test(fnm,F_OK);
rc += test(fnm,R_OK);
rc += test(fnm,W_OK);
rc += test(fnm,X_OK);
if (!rc) {
printf("OK\n");
}
return 0;
}
\
 
 \ /
  Last update: 2005-03-22 13:51    [W:0.025 / U:0.108 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site