Implement issetugid syscall
Implement issetugid syscall and provide a test. This gets rid of the scary "Unsecure. Implement me" warning during compilation.
This commit is contained in:
		
							parent
							
								
									ef99a7a3dc
								
							
						
					
					
						commit
						b4fb061802
					
				| @ -100,7 +100,7 @@ | |||||||
| #define EXEC_RESTART	102	/* to PM: final part of exec for RS */ | #define EXEC_RESTART	102	/* to PM: final part of exec for RS */ | ||||||
| #define PROCSTAT	103	/* to PM */ | #define PROCSTAT	103	/* to PM */ | ||||||
| #define GETPROCNR	104	/* to PM */ | #define GETPROCNR	104	/* to PM */ | ||||||
| 
 | #define ISSETUGID	106	/* to PM: ask if process is tainted */ | ||||||
| #define GETEPINFO_O	107	/* to PM: get pid/uid/gid of an endpoint */ | #define GETEPINFO_O	107	/* to PM: get pid/uid/gid of an endpoint */ | ||||||
| #define ADDDMA		108	/* to PM: inform PM about a region of memory | #define ADDDMA		108	/* to PM: inform PM about a region of memory | ||||||
| 				 * that is used for bus-master DMA | 				 * that is used for bus-master DMA | ||||||
|  | |||||||
| @ -165,6 +165,7 @@ struct exec_newmem | |||||||
| 	time_t enst_ctime;	/* Last changed time of executable file */ | 	time_t enst_ctime;	/* Last changed time of executable file */ | ||||||
| 	uid_t new_uid;		/* Process UID after exec */ | 	uid_t new_uid;		/* Process UID after exec */ | ||||||
| 	gid_t new_gid;		/* Process GID after exec */ | 	gid_t new_gid;		/* Process GID after exec */ | ||||||
|  | 	int setugid;		/* Process is setuid or setgid */ | ||||||
| 	char progname[16];	/* Should be at least PROC_NAME_LEN */ | 	char progname[16];	/* Should be at least PROC_NAME_LEN */ | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -116,6 +116,7 @@ _PROTOTYPE( pid_t getpid, (void)					); | |||||||
| _PROTOTYPE( pid_t getppid, (void)					); | _PROTOTYPE( pid_t getppid, (void)					); | ||||||
| _PROTOTYPE( uid_t getuid, (void)					); | _PROTOTYPE( uid_t getuid, (void)					); | ||||||
| _PROTOTYPE( int isatty, (int _fd)					); | _PROTOTYPE( int isatty, (int _fd)					); | ||||||
|  | _PROTOTYPE( int issetugid, (void)					); | ||||||
| _PROTOTYPE( int link, (const char *_existing, const char *_new)		); | _PROTOTYPE( int link, (const char *_existing, const char *_new)		); | ||||||
| _PROTOTYPE( off_t lseek, (int _fd, off_t _offset, int _whence)		); | _PROTOTYPE( off_t lseek, (int _fd, off_t _offset, int _whence)		); | ||||||
| _PROTOTYPE( long pathconf, (const char *_path, int _name)		); | _PROTOTYPE( long pathconf, (const char *_path, int _name)		); | ||||||
|  | |||||||
| @ -69,6 +69,7 @@ SRCS+=  \ | |||||||
| 	hypot.c \ | 	hypot.c \ | ||||||
| 	index.c \ | 	index.c \ | ||||||
| 	initgroups.c \ | 	initgroups.c \ | ||||||
|  | 	issetugid.c \ | ||||||
| 	itoa.c \ | 	itoa.c \ | ||||||
| 	loadname.c \ | 	loadname.c \ | ||||||
| 	lock.c \ | 	lock.c \ | ||||||
|  | |||||||
							
								
								
									
										14
									
								
								lib/libc/other/issetugid.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								lib/libc/other/issetugid.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | |||||||
|  | #include <sys/cdefs.h> | ||||||
|  | #include <lib.h> | ||||||
|  | 
 | ||||||
|  | #include <unistd.h> | ||||||
|  | 
 | ||||||
|  | int issetugid(void) | ||||||
|  | { | ||||||
|  | 	int r; | ||||||
|  | 	message m; | ||||||
|  | 
 | ||||||
|  | 	r = _syscall(PM_PROC_NR, ISSETUGID, &m); | ||||||
|  | 	if (r == -1) return 0;	/* Default to old behavior */ | ||||||
|  | 	return(r); | ||||||
|  | } | ||||||
| @ -6,6 +6,10 @@ | |||||||
| 
 | 
 | ||||||
| int issetugid(void) | int issetugid(void) | ||||||
| { | { | ||||||
| #warning Unsecure. Implement me. | 	int r; | ||||||
| 	return 0; | 	message m; | ||||||
|  | 
 | ||||||
|  | 	r = _syscall(PM_PROC_NR, ISSETUGID, &m); | ||||||
|  | 	if (r == -1) return 0;	/* Default to old behavior */ | ||||||
|  | 	return(r); | ||||||
| } | } | ||||||
|  | |||||||
| @ -43,7 +43,7 @@ FORWARD _PROTOTYPE( int exec_newmem, (int proc_e, vir_bytes text_addr, vir_bytes | |||||||
| 		       int is_elf, dev_t st_dev, ino_t st_ino, time_t ctime, | 		       int is_elf, dev_t st_dev, ino_t st_ino, time_t ctime, | ||||||
| 		       char *progname, int new_uid, int new_gid, | 		       char *progname, int new_uid, int new_gid, | ||||||
| 		       vir_bytes *stack_topp, int *load_textp, | 		       vir_bytes *stack_topp, int *load_textp, | ||||||
| 		       int *allow_setuidp)				); | 		       int *setugidp)					); | ||||||
| FORWARD _PROTOTYPE( int is_script, (const char *exec_hdr, size_t exec_len)); | FORWARD _PROTOTYPE( int is_script, (const char *exec_hdr, size_t exec_len)); | ||||||
| FORWARD _PROTOTYPE( int patch_stack, (struct vnode *vp, char stack[ARG_MAX], | FORWARD _PROTOTYPE( int patch_stack, (struct vnode *vp, char stack[ARG_MAX], | ||||||
| 		       vir_bytes *stk_bytes, char path[PATH_MAX])	); | 		       vir_bytes *stk_bytes, char path[PATH_MAX])	); | ||||||
| @ -168,6 +168,7 @@ PUBLIC int pm_exec(int proc_e, char *path, vir_bytes path_len, char *frame, | |||||||
| 
 | 
 | ||||||
| 	strncpy(execi.progname, cp, PROC_NAME_LEN-1); | 	strncpy(execi.progname, cp, PROC_NAME_LEN-1); | ||||||
| 	execi.progname[PROC_NAME_LEN-1] = '\0'; | 	execi.progname[PROC_NAME_LEN-1] = '\0'; | ||||||
|  | 	execi.setugid = 0; | ||||||
| 
 | 
 | ||||||
| 	/* Open executable */ | 	/* Open executable */ | ||||||
| 	if ((vp = eat_path(&resolve, fp)) == NULL) { | 	if ((vp = eat_path(&resolve, fp)) == NULL) { | ||||||
| @ -188,8 +189,14 @@ PUBLIC int pm_exec(int proc_e, char *path, vir_bytes path_len, char *frame, | |||||||
| 
 | 
 | ||||||
|         if (round == 0) { |         if (round == 0) { | ||||||
| 		/* Deal with setuid/setgid executables */ | 		/* Deal with setuid/setgid executables */ | ||||||
|             if (vp->v_mode & I_SET_UID_BIT) execi.new_uid = vp->v_uid; | 		if (vp->v_mode & I_SET_UID_BIT) { | ||||||
|             if (vp->v_mode & I_SET_GID_BIT) execi.new_gid = vp->v_gid; | 			execi.new_uid = vp->v_uid; | ||||||
|  | 			execi.setugid = 1; | ||||||
|  | 		} | ||||||
|  | 		if (vp->v_mode & I_SET_GID_BIT) { | ||||||
|  | 			execi.new_gid = vp->v_gid; | ||||||
|  | 			execi.setugid = 1; | ||||||
|  | 		} | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| 	r = map_header(&execi.hdr, execi.vp); | 	r = map_header(&execi.hdr, execi.vp); | ||||||
| @ -240,7 +247,9 @@ PUBLIC int pm_exec(int proc_e, char *path, vir_bytes path_len, char *frame, | |||||||
|   if (r != OK) goto pm_execfinal; |   if (r != OK) goto pm_execfinal; | ||||||
|   clo_exec(rfp); |   clo_exec(rfp); | ||||||
| 
 | 
 | ||||||
|   if (execi.allow_setuid) { |   if (execi.setugid) { | ||||||
|  | 	/* If after loading the image we're still allowed to run with
 | ||||||
|  | 	 * setuid or setgid, change credentials now */ | ||||||
| 	rfp->fp_effuid = execi.new_uid; | 	rfp->fp_effuid = execi.new_uid; | ||||||
| 	rfp->fp_effgid = execi.new_gid; | 	rfp->fp_effgid = execi.new_gid; | ||||||
|   } |   } | ||||||
| @ -286,7 +295,7 @@ PRIVATE int load_aout(struct exec_info *execi) | |||||||
| 		  execi->frame_len, sep_id, 0 /* is_elf */, vp->v_dev, vp->v_inode_nr, | 		  execi->frame_len, sep_id, 0 /* is_elf */, vp->v_dev, vp->v_inode_nr, | ||||||
| 		  execi->sb.st_ctime, | 		  execi->sb.st_ctime, | ||||||
| 		  execi->progname, execi->new_uid, execi->new_gid, | 		  execi->progname, execi->new_uid, execi->new_gid, | ||||||
| 		  &execi->stack_top, &execi->load_text, &execi->allow_setuid); | 		  &execi->stack_top, &execi->load_text, &execi->setugid); | ||||||
| 
 | 
 | ||||||
|   if (r != OK) { |   if (r != OK) { | ||||||
|         printf("VFS: load_aout: exec_newmem failed: %d\n", r); |         printf("VFS: load_aout: exec_newmem failed: %d\n", r); | ||||||
| @ -343,7 +352,7 @@ PRIVATE int load_elf(struct exec_info *execi) | |||||||
| 		  tot_bytes, execi->frame_len, sep_id, is_elf, | 		  tot_bytes, execi->frame_len, sep_id, is_elf, | ||||||
| 		  vp->v_dev, vp->v_inode_nr, execi->sb.st_ctime, | 		  vp->v_dev, vp->v_inode_nr, execi->sb.st_ctime, | ||||||
| 		  execi->progname, execi->new_uid, execi->new_gid, | 		  execi->progname, execi->new_uid, execi->new_gid, | ||||||
| 		  &execi->stack_top, &execi->load_text, &execi->allow_setuid); | 		  &execi->stack_top, &execi->load_text, &execi->setugid); | ||||||
| 
 | 
 | ||||||
|   if (r != OK) { |   if (r != OK) { | ||||||
|         printf("VFS: load_elf: exec_newmem failed: %d\n", r); |         printf("VFS: load_elf: exec_newmem failed: %d\n", r); | ||||||
| @ -381,7 +390,7 @@ PRIVATE int exec_newmem( | |||||||
|   int new_gid, |   int new_gid, | ||||||
|   vir_bytes *stack_topp, |   vir_bytes *stack_topp, | ||||||
|   int *load_textp, |   int *load_textp, | ||||||
|   int *allow_setuidp |   int *setugidp | ||||||
| ) | ) | ||||||
| { | { | ||||||
| /* Allocate a new memory map for a process that tries to exec */ | /* Allocate a new memory map for a process that tries to exec */ | ||||||
| @ -389,6 +398,8 @@ PRIVATE int exec_newmem( | |||||||
|   struct exec_newmem e; |   struct exec_newmem e; | ||||||
|   message m; |   message m; | ||||||
| 
 | 
 | ||||||
|  |   assert(setugidp != NULL); | ||||||
|  | 
 | ||||||
|   e.text_addr = text_addr; |   e.text_addr = text_addr; | ||||||
|   e.text_bytes = text_bytes; |   e.text_bytes = text_bytes; | ||||||
|   e.data_addr = data_addr; |   e.data_addr = data_addr; | ||||||
| @ -402,6 +413,7 @@ PRIVATE int exec_newmem( | |||||||
|   e.enst_ctime = ctime; |   e.enst_ctime = ctime; | ||||||
|   e.new_uid    = new_uid; |   e.new_uid    = new_uid; | ||||||
|   e.new_gid    = new_gid; |   e.new_gid    = new_gid; | ||||||
|  |   e.setugid    = *setugidp; | ||||||
|   strncpy(e.progname, progname, sizeof(e.progname)-1); |   strncpy(e.progname, progname, sizeof(e.progname)-1); | ||||||
|   e.progname[sizeof(e.progname)-1] = '\0'; |   e.progname[sizeof(e.progname)-1] = '\0'; | ||||||
| 
 | 
 | ||||||
| @ -412,7 +424,7 @@ PRIVATE int exec_newmem( | |||||||
| 
 | 
 | ||||||
|   *stack_topp = m.m1_i1; |   *stack_topp = m.m1_i1; | ||||||
|   *load_textp = !!(m.m1_i2 & EXC_NM_RF_LOAD_TEXT); |   *load_textp = !!(m.m1_i2 & EXC_NM_RF_LOAD_TEXT); | ||||||
|   *allow_setuidp = !!(m.m1_i2 & EXC_NM_RF_ALLOW_SETUID); |   *setugidp = !!(m.m1_i2 & EXC_NM_RF_ALLOW_SETUID); | ||||||
| 
 | 
 | ||||||
|   return(m.m_type); |   return(m.m_type); | ||||||
| } | } | ||||||
|  | |||||||
| @ -10,7 +10,7 @@ struct exec_info { | |||||||
|     uid_t new_uid;			/* Process UID after exec */ |     uid_t new_uid;			/* Process UID after exec */ | ||||||
|     gid_t new_gid;			/* Process GID after exec */ |     gid_t new_gid;			/* Process GID after exec */ | ||||||
|     int load_text;			/* Load text section? */ |     int load_text;			/* Load text section? */ | ||||||
|     int allow_setuid;			/* Allow setuid execution? */ |     int setugid;			/* Allow set{u,g}id execution? */ | ||||||
|     struct vnode *vp;			/* Exec file's vnode */ |     struct vnode *vp;			/* Exec file's vnode */ | ||||||
|     struct stat sb;			/* Exec file's stat structure */ |     struct stat sb;			/* Exec file's stat structure */ | ||||||
|     char progname[PROC_NAME_LEN];	/* Program name */ |     char progname[PROC_NAME_LEN];	/* Program name */ | ||||||
|  | |||||||
| @ -81,16 +81,30 @@ PUBLIC int do_exec_newmem() | |||||||
| 	if (r != OK) | 	if (r != OK) | ||||||
| 		panic("do_exec_newmem: sys_datacopy failed: %d", r); | 		panic("do_exec_newmem: sys_datacopy failed: %d", r); | ||||||
| 
 | 
 | ||||||
| 	if((r=vm_exec_newmem(proc_e, &args, sizeof(args), &stack_top, &flags)) == OK) { | 	if ((r = vm_exec_newmem(proc_e, &args, sizeof(args), &stack_top, | ||||||
| 		allow_setuid= 0;                /* Do not allow setuid execution */   | 				&flags)) == OK) { | ||||||
|  | 		allow_setuid = 0;	/* Do not allow setuid execution */ | ||||||
|  | 		rmp->mp_flags &= ~TAINTED;	/* By default not tainted */ | ||||||
| 
 | 
 | ||||||
| 		if (rmp->mp_tracer == NO_TRACER) { | 		if (rmp->mp_tracer == NO_TRACER) { | ||||||
| 			/* Okay, setuid execution is allowed */ | 			/* Okay, setuid execution is allowed */ | ||||||
| 			allow_setuid= 1; | 			allow_setuid = 1; | ||||||
|  | 
 | ||||||
| 			rmp->mp_effuid = args.new_uid; | 			rmp->mp_effuid = args.new_uid; | ||||||
| 			rmp->mp_effgid = args.new_gid; | 			rmp->mp_effgid = args.new_gid; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | 		/* A process is considered 'tainted' when it's executing with
 | ||||||
|  | 		 * setuid or setgid bit set, or when the real{u,g}id doesn't | ||||||
|  | 		 * match the eff{u,g}id, respectively. */ | ||||||
|  | 		if (allow_setuid && args.setugid) { | ||||||
|  | 			/* Program has setuid and/or setgid bits set */ | ||||||
|  | 			rmp->mp_flags |= TAINTED; | ||||||
|  | 		} else if (rmp->mp_effuid != rmp->mp_realuid || | ||||||
|  | 			   rmp->mp_effgid != rmp->mp_realgid) { | ||||||
|  | 			rmp->mp_flags |= TAINTED; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		/* System will save command line for debugging, ps(1) output, etc. */ | 		/* System will save command line for debugging, ps(1) output, etc. */ | ||||||
| 		strncpy(rmp->mp_name, args.progname, PROC_NAME_LEN-1); | 		strncpy(rmp->mp_name, args.progname, PROC_NAME_LEN-1); | ||||||
| 		rmp->mp_name[PROC_NAME_LEN-1] = '\0'; | 		rmp->mp_name[PROC_NAME_LEN-1] = '\0'; | ||||||
|  | |||||||
| @ -103,7 +103,7 @@ PUBLIC int do_fork() | |||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   /* Inherit only these flags. In normal fork(), PRIV_PROC is not inherited. */ |   /* Inherit only these flags. In normal fork(), PRIV_PROC is not inherited. */ | ||||||
|   rmc->mp_flags &= (IN_USE|DELAY_CALL); |   rmc->mp_flags &= (IN_USE|DELAY_CALL|TAINTED); | ||||||
|   rmc->mp_child_utime = 0;		/* reset administration */ |   rmc->mp_child_utime = 0;		/* reset administration */ | ||||||
|   rmc->mp_child_stime = 0;		/* reset administration */ |   rmc->mp_child_stime = 0;		/* reset administration */ | ||||||
|   rmc->mp_exitstatus = 0; |   rmc->mp_exitstatus = 0; | ||||||
|  | |||||||
| @ -18,7 +18,8 @@ | |||||||
|  *===========================================================================*/ |  *===========================================================================*/ | ||||||
| PUBLIC int do_get() | PUBLIC int do_get() | ||||||
| { | { | ||||||
| /* Handle GETUID, GETGID, GETGROUPS, GETGROUPS_O, GETPID, GETPGRP, GETSID.
 | /* Handle GETUID, GETGID, GETGROUPS, GETGROUPS_O, GETPID, GETPGRP, GETSID,
 | ||||||
|  |    ISSETUGID. | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
|   register struct mproc *rmp = mp; |   register struct mproc *rmp = mp; | ||||||
| @ -103,6 +104,10 @@ PUBLIC int do_get() | |||||||
| 			r = target->mp_procgrp; | 			r = target->mp_procgrp; | ||||||
| 		break; | 		break; | ||||||
| 	} | 	} | ||||||
|  | 	case ISSETUGID: | ||||||
|  | 		r = !!(rmp->mp_flags & TAINTED); | ||||||
|  | 		break; | ||||||
|  | 
 | ||||||
| 	default: | 	default: | ||||||
| 		r = EINVAL; | 		r = EINVAL; | ||||||
| 		break;	 | 		break;	 | ||||||
|  | |||||||
| @ -91,5 +91,6 @@ EXTERN struct mproc { | |||||||
| #define TRACE_EXIT	0x08000	/* tracer is forcing this process to exit */ | #define TRACE_EXIT	0x08000	/* tracer is forcing this process to exit */ | ||||||
| #define TRACE_ZOMBIE	0x10000	/* waiting for tracer to issue WAIT call */ | #define TRACE_ZOMBIE	0x10000	/* waiting for tracer to issue WAIT call */ | ||||||
| #define DELAY_CALL	0x20000	/* waiting for call before sending signal */ | #define DELAY_CALL	0x20000	/* waiting for call before sending signal */ | ||||||
|  | #define TAINTED		0x40000 /* process is 'tainted' */ | ||||||
| 
 | 
 | ||||||
| #define MP_MAGIC	0xC0FFEE0 | #define MP_MAGIC	0xC0FFEE0 | ||||||
|  | |||||||
| @ -117,7 +117,7 @@ _PROTOTYPE (int (*call_vec[]), (void) ) = { | |||||||
| 	do_procstat,	/* 103 = procstat */ | 	do_procstat,	/* 103 = procstat */ | ||||||
| 	do_getprocnr,	/* 104 = getprocnr */ | 	do_getprocnr,	/* 104 = getprocnr */ | ||||||
| 	no_sys,		/* 105 = unused */ | 	no_sys,		/* 105 = unused */ | ||||||
| 	no_sys,		/* 106 = unused */ | 	do_get,		/* 106 = issetugid */ | ||||||
| 	do_getepinfo_o,	/* 107 = getepinfo XXX: old implementation*/ | 	do_getepinfo_o,	/* 107 = getepinfo XXX: old implementation*/ | ||||||
| 	do_adddma,	/* 108 = adddma */ | 	do_adddma,	/* 108 = adddma */ | ||||||
| 	do_deldma,	/* 109 = deldma */ | 	do_deldma,	/* 109 = deldma */ | ||||||
|  | |||||||
| @ -41,7 +41,7 @@ static int exec_newmem(int proc_e, vir_bytes text_addr, vir_bytes text_bytes, | |||||||
| 		       int is_elf, dev_t st_dev, ino_t st_ino, time_t ctime, | 		       int is_elf, dev_t st_dev, ino_t st_ino, time_t ctime, | ||||||
| 		       char *progname, int new_uid, int new_gid, | 		       char *progname, int new_uid, int new_gid, | ||||||
| 		       vir_bytes *stack_topp, int *load_textp, | 		       vir_bytes *stack_topp, int *load_textp, | ||||||
| 		       int *allow_setuidp); | 		       int *setugidp); | ||||||
| static int is_script(const char *exec_hdr, size_t exec_len); | static int is_script(const char *exec_hdr, size_t exec_len); | ||||||
| static int patch_stack(struct vnode *vp, char stack[ARG_MAX], | static int patch_stack(struct vnode *vp, char stack[ARG_MAX], | ||||||
| 		       vir_bytes *stk_bytes); | 		       vir_bytes *stk_bytes); | ||||||
| @ -118,6 +118,7 @@ PUBLIC int pm_exec(int proc_e, char *path, vir_bytes path_len, char *frame, | |||||||
| 
 | 
 | ||||||
| 	strncpy(execi.progname, cp, PROC_NAME_LEN-1); | 	strncpy(execi.progname, cp, PROC_NAME_LEN-1); | ||||||
| 	execi.progname[PROC_NAME_LEN-1] = '\0'; | 	execi.progname[PROC_NAME_LEN-1] = '\0'; | ||||||
|  | 	execi.setugid = 0; | ||||||
| 
 | 
 | ||||||
| 	/* Open executable */ | 	/* Open executable */ | ||||||
| 	if ((vp = eat_path(PATH_NOFLAGS, fp)) == NULL) return(err_code); | 	if ((vp = eat_path(PATH_NOFLAGS, fp)) == NULL) return(err_code); | ||||||
| @ -137,8 +138,14 @@ PUBLIC int pm_exec(int proc_e, char *path, vir_bytes path_len, char *frame, | |||||||
| 
 | 
 | ||||||
|         if (round == 0) { |         if (round == 0) { | ||||||
| 		/* Deal with setuid/setgid executables */ | 		/* Deal with setuid/setgid executables */ | ||||||
|             if (vp->v_mode & I_SET_UID_BIT) execi.new_uid = vp->v_uid; | 		if (vp->v_mode & I_SET_UID_BIT) { | ||||||
|             if (vp->v_mode & I_SET_GID_BIT) execi.new_gid = vp->v_gid; | 			execi.new_uid = vp->v_uid; | ||||||
|  | 			execi.setugid = 1; | ||||||
|  | 		} | ||||||
|  | 		if (vp->v_mode & I_SET_GID_BIT) { | ||||||
|  | 			execi.new_gid = vp->v_gid; | ||||||
|  | 			execi.setugid = 1; | ||||||
|  | 		} | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| 	r = map_header(&execi.hdr, execi.vp); | 	r = map_header(&execi.hdr, execi.vp); | ||||||
| @ -190,7 +197,9 @@ PUBLIC int pm_exec(int proc_e, char *path, vir_bytes path_len, char *frame, | |||||||
|   if (r != OK) return(r); |   if (r != OK) return(r); | ||||||
|   clo_exec(rfp); |   clo_exec(rfp); | ||||||
| 
 | 
 | ||||||
|   if (execi.allow_setuid) { |   if (execi.setugid) { | ||||||
|  | 	/* If after loading the image we're still allowed to run with
 | ||||||
|  | 	 * setuid or setgid, change the credentials now */ | ||||||
| 	rfp->fp_effuid = execi.new_uid; | 	rfp->fp_effuid = execi.new_uid; | ||||||
| 	rfp->fp_effgid = execi.new_gid; | 	rfp->fp_effgid = execi.new_gid; | ||||||
|   } |   } | ||||||
| @ -230,7 +239,7 @@ static int load_aout(struct exec_info *execi) | |||||||
| 		  execi->frame_len, sep_id, 0 /* is_elf */, vp->v_dev, vp->v_inode_nr, | 		  execi->frame_len, sep_id, 0 /* is_elf */, vp->v_dev, vp->v_inode_nr, | ||||||
| 		  execi->sb.st_ctime, | 		  execi->sb.st_ctime, | ||||||
| 		  execi->progname, execi->new_uid, execi->new_gid, | 		  execi->progname, execi->new_uid, execi->new_gid, | ||||||
| 		  &execi->stack_top, &execi->load_text, &execi->allow_setuid); | 		  &execi->stack_top, &execi->load_text, &execi->setugid); | ||||||
| 
 | 
 | ||||||
|   if (r != OK) { |   if (r != OK) { | ||||||
|         printf("VFS: load_aout: exec_newmem failed: %d\n", r); |         printf("VFS: load_aout: exec_newmem failed: %d\n", r); | ||||||
| @ -282,7 +291,7 @@ static int load_elf(struct exec_info *execi) | |||||||
| 		  tot_bytes, execi->frame_len, sep_id, is_elf, | 		  tot_bytes, execi->frame_len, sep_id, is_elf, | ||||||
| 		  vp->v_dev, vp->v_inode_nr, execi->sb.st_ctime, | 		  vp->v_dev, vp->v_inode_nr, execi->sb.st_ctime, | ||||||
| 		  execi->progname, execi->new_uid, execi->new_gid, | 		  execi->progname, execi->new_uid, execi->new_gid, | ||||||
| 		  &execi->stack_top, &execi->load_text, &execi->allow_setuid); | 		  &execi->stack_top, &execi->load_text, &execi->setugid); | ||||||
| 
 | 
 | ||||||
|   if (r != OK) { |   if (r != OK) { | ||||||
|         printf("VFS: load_elf: exec_newmem failed: %d\n", r); |         printf("VFS: load_elf: exec_newmem failed: %d\n", r); | ||||||
| @ -320,13 +329,15 @@ static int exec_newmem( | |||||||
|   int new_gid, |   int new_gid, | ||||||
|   vir_bytes *stack_topp, |   vir_bytes *stack_topp, | ||||||
|   int *load_textp, |   int *load_textp, | ||||||
|   int *allow_setuidp |   int *setugidp | ||||||
| ) | ) | ||||||
| { | { | ||||||
|   int r; |   int r; | ||||||
|   struct exec_newmem e; |   struct exec_newmem e; | ||||||
|   message m; |   message m; | ||||||
| 
 | 
 | ||||||
|  |   assert(setugidp != NULL); | ||||||
|  | 
 | ||||||
|   e.text_addr = text_addr; |   e.text_addr = text_addr; | ||||||
|   e.text_bytes = text_bytes; |   e.text_bytes = text_bytes; | ||||||
|   e.data_addr = data_addr; |   e.data_addr = data_addr; | ||||||
| @ -340,6 +351,7 @@ static int exec_newmem( | |||||||
|   e.enst_ctime = ctime; |   e.enst_ctime = ctime; | ||||||
|   e.new_uid    = new_uid; |   e.new_uid    = new_uid; | ||||||
|   e.new_gid    = new_gid; |   e.new_gid    = new_gid; | ||||||
|  |   e.setugid    = *setugidp; | ||||||
|   strncpy(e.progname, progname, sizeof(e.progname)-1); |   strncpy(e.progname, progname, sizeof(e.progname)-1); | ||||||
|   e.progname[sizeof(e.progname)-1] = '\0'; |   e.progname[sizeof(e.progname)-1] = '\0'; | ||||||
| 
 | 
 | ||||||
| @ -350,7 +362,7 @@ static int exec_newmem( | |||||||
| 
 | 
 | ||||||
|   *stack_topp = m.m1_i1; |   *stack_topp = m.m1_i1; | ||||||
|   *load_textp = !!(m.m1_i2 & EXC_NM_RF_LOAD_TEXT); |   *load_textp = !!(m.m1_i2 & EXC_NM_RF_LOAD_TEXT); | ||||||
|   *allow_setuidp = !!(m.m1_i2 & EXC_NM_RF_ALLOW_SETUID); |   *setugidp = !!(m.m1_i2 & EXC_NM_RF_ALLOW_SETUID); | ||||||
| 
 | 
 | ||||||
|   return(m.m_type); |   return(m.m_type); | ||||||
| } | } | ||||||
|  | |||||||
| @ -10,7 +10,7 @@ struct exec_info { | |||||||
|     uid_t new_uid;			/* Process UID after exec */ |     uid_t new_uid;			/* Process UID after exec */ | ||||||
|     gid_t new_gid;			/* Process GID after exec */ |     gid_t new_gid;			/* Process GID after exec */ | ||||||
|     int load_text;			/* Load text section? */ |     int load_text;			/* Load text section? */ | ||||||
|     int allow_setuid;			/* Allow setuid execution? */ |     int setugid;			/* Allow set{u,g}id execution? */ | ||||||
|     struct vnode *vp;			/* Exec file's vnode */ |     struct vnode *vp;			/* Exec file's vnode */ | ||||||
|     struct stat sb;			/* Exec file's stat structure */ |     struct stat sb;			/* Exec file's stat structure */ | ||||||
|     char progname[PROC_NAME_LEN];	/* Program name */ |     char progname[PROC_NAME_LEN];	/* Program name */ | ||||||
|  | |||||||
| @ -16,10 +16,10 @@ OBJ=	test1  test2  test3  test4  test5  test6  test7  test8  test9  \ | |||||||
| 	test30 test31 test32        test34 test35 test36 test37 test38 \
 | 	test30 test31 test32        test34 test35 test36 test37 test38 \
 | ||||||
| 	test39 t10a t11a t11b test40 t40a t40b t40c t40d t40e t40f test41 \
 | 	test39 t10a t11a t11b test40 t40a t40b t40c t40d t40e t40f test41 \
 | ||||||
| 	test42 test45 test47 test49 test50 test51 test52 test53 \
 | 	test42 test45 test47 test49 test50 test51 test52 test53 \
 | ||||||
| 	test54 test56 test58 | 	test54 test56 test58 t60a t60b | ||||||
| 
 | 
 | ||||||
| BIGOBJ=  test20 test24 | BIGOBJ=  test20 test24 | ||||||
| ROOTOBJ= test11 test33 test43 test44 test46 | ROOTOBJ= test11 test33 test43 test44 test46 test60 | ||||||
| GCCOBJ=  test45-gcc test48 test49-gcc test55 | GCCOBJ=  test45-gcc test48 test49-gcc test55 | ||||||
| GCCFPUOBJ= test51-gcc test52-gcc | GCCFPUOBJ= test51-gcc test52-gcc | ||||||
| OTHEROBJ= test57 test59 | OTHEROBJ= test57 test59 | ||||||
| @ -53,7 +53,9 @@ depend: .gitignore | |||||||
| clean:	 | clean:	 | ||||||
| 	$(MAKE) -C select clean | 	$(MAKE) -C select clean | ||||||
| 	-rm -rf *.o *.s *.bak test? test?? test??-gcc t10a t11a t11b \
 | 	-rm -rf *.o *.s *.bak test? test?? test??-gcc t10a t11a t11b \
 | ||||||
| 		t40a t40b t40c t40d t40e t40f t43 DIR* | 		t40a t40b t40c t40d t40e t40f t43 \
 | ||||||
|  | 		t60a t60b \
 | ||||||
|  | 		DIR* | ||||||
| 
 | 
 | ||||||
| test1:	test1.c | test1:	test1.c | ||||||
| test2:	test2.c | test2:	test2.c | ||||||
| @ -128,3 +130,6 @@ test57: test57.c test57loop.S | |||||||
| test58: test58.c | test58: test58.c | ||||||
| test59: test59.c | test59: test59.c | ||||||
| 	$(CC) $(CFLAGS) -o $@ $@.c -lmthread  | 	$(CC) $(CFLAGS) -o $@ $@.c -lmthread  | ||||||
|  | test60: test60.c | ||||||
|  | t60a: t60a.c | ||||||
|  | t60b: t60b.c | ||||||
|  | |||||||
							
								
								
									
										1
									
								
								test/run
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								test/run
									
									
									
									
									
								
							| @ -15,6 +15,7 @@ tests="   1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 \ | |||||||
|          21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 \ |          21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 \ | ||||||
|          41 42 43 44 45 45-gcc 46 47 48 49 49-gcc 50 \ |          41 42 43 44 45 45-gcc 46 47 48 49 49-gcc 50 \ | ||||||
|          51 51-gcc 52 52-gcc 53 54 55 56 57 58 59\ |          51 51-gcc 52 52-gcc 53 54 55 56 57 58 59\ | ||||||
|  |          60 \ | ||||||
| 	 sh1.sh sh2.sh" | 	 sh1.sh sh2.sh" | ||||||
| tests_no=`expr 0` | tests_no=`expr 0` | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										18
									
								
								test/t60a.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								test/t60a.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | |||||||
|  | #include <unistd.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <stdio.h> | ||||||
|  | 
 | ||||||
|  | int main(int argc, char *argv[]) | ||||||
|  | { | ||||||
|  | /* Return our tainted state to the parent */ | ||||||
|  |   int newmode; | ||||||
|  |   char cmd[30]; | ||||||
|  | 
 | ||||||
|  |   if (argc < 2) return(-2); | ||||||
|  |   if ((newmode = atoi(argv[1])) > 0) { | ||||||
|  | 	snprintf(cmd, sizeof(cmd), "chmod %o %s", newmode, argv[0]); | ||||||
|  | 	system(cmd); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return(issetugid()); | ||||||
|  | } | ||||||
							
								
								
									
										23
									
								
								test/t60b.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								test/t60b.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,23 @@ | |||||||
|  | #include <sys/types.h> | ||||||
|  | #include <sys/wait.h> | ||||||
|  | #include <unistd.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <stdio.h> | ||||||
|  | 
 | ||||||
|  | int main(int argc, char **argv) | ||||||
|  | { | ||||||
|  | /* Return the tainted state of our child to our parent */ | ||||||
|  |   pid_t childpid; | ||||||
|  |   int status; | ||||||
|  | 
 | ||||||
|  |   childpid = fork(); | ||||||
|  |   if (childpid == (pid_t) -1) exit(-2); | ||||||
|  |   else if (childpid == 0) { | ||||||
|  | 	exit(issetugid()); | ||||||
|  |   } else { | ||||||
|  | 	wait(&status); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return(WEXITSTATUS(status)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
							
								
								
									
										265
									
								
								test/test60.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										265
									
								
								test/test60.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,265 @@ | |||||||
|  | #include <sys/types.h> | ||||||
|  | #include <sys/wait.h> | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <unistd.h> | ||||||
|  | 
 | ||||||
|  | #define MAX_ERROR 5 | ||||||
|  | #include "common.c" | ||||||
|  | 
 | ||||||
|  | int subtest = -1; | ||||||
|  | 
 | ||||||
|  | void test_self(void); | ||||||
|  | void test_setnone(void); | ||||||
|  | void test_setuid(void); | ||||||
|  | void test_setgid(void); | ||||||
|  | void test_effugid(void); | ||||||
|  | int execute(const char *prog, const char *arg); | ||||||
|  | 
 | ||||||
|  | int execute(const char *prog, const char *arg) | ||||||
|  | { | ||||||
|  |   pid_t childpid; | ||||||
|  |   int status; | ||||||
|  |   char cmd[30]; | ||||||
|  | 
 | ||||||
|  |   snprintf(cmd, sizeof(cmd), "./%s", prog); | ||||||
|  | 
 | ||||||
|  |   childpid = fork(); | ||||||
|  |   if (childpid == (pid_t) -1) { | ||||||
|  | 	return(-2); | ||||||
|  |   } else if (childpid == 0) { | ||||||
|  | 	if (execl(cmd, prog, arg, NULL) == -1) { | ||||||
|  | 		exit(-2); | ||||||
|  | 	} | ||||||
|  | 	return(-2);	/* Never reached */ | ||||||
|  |   } else { | ||||||
|  | 	wait(&status); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return(WEXITSTATUS(status)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void test_setgid(void) | ||||||
|  | { | ||||||
|  | /* Execve a new process that has setgid bits set */ | ||||||
|  |   subtest = 3; | ||||||
|  | 
 | ||||||
|  |   /* When we exec a new process which has setgid set, that process should
 | ||||||
|  |    * be tainted. | ||||||
|  |    */ | ||||||
|  |   system("chmod 2755 setgid"); | ||||||
|  |   if (execute("setgid", "0000") != 1) e(2); | ||||||
|  | 
 | ||||||
|  |   /* When we exec a new process which has setgid set, but unsets that bit
 | ||||||
|  |    * before calling issetugid() should still be tainted | ||||||
|  |    */ | ||||||
|  |   system("chmod 2755 setgid"); | ||||||
|  |   if (execute("setgid", "0755") != 1) e(3); | ||||||
|  | 
 | ||||||
|  |   /* When we exec a new process which has setgid set, and then also sets
 | ||||||
|  |    * setuid before calling issetugid() should still be tainted | ||||||
|  |    */ | ||||||
|  |   system("chmod 2755 setgid"); | ||||||
|  |   if (execute("setgid", "06755") != 1) e(4); | ||||||
|  | 
 | ||||||
|  |   /* When we exec a new process that has setgid set, and which upon
 | ||||||
|  |    * execution forks, the forked child should also be tainted */ | ||||||
|  |   system("chmod 2755 setgidfork"); | ||||||
|  |   if (execute("setgidfork", "0000") != 1) e(5); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void test_setuid(void) | ||||||
|  | { | ||||||
|  | /* Execve a new process that has setuid bits set */ | ||||||
|  |   subtest = 4; | ||||||
|  | 
 | ||||||
|  |   /* When we exec a new process which has setuid set, that process should
 | ||||||
|  |    * be tainted. | ||||||
|  |    */ | ||||||
|  |   system("chmod 4755 setuid"); | ||||||
|  |   if (execute("setuid", "0000") != 1) e(1); | ||||||
|  | 
 | ||||||
|  |   /* When we exec a new process which has setuid set, but unsets that bit
 | ||||||
|  |    * before calling issetugid() should still be tainted | ||||||
|  |    */ | ||||||
|  |   system("chmod 4755 setuid"); | ||||||
|  |   if (execute("setuid", "0755") != 1) e(2); | ||||||
|  | 
 | ||||||
|  |   /* When we exec a new process which has setuid set, and then also sets
 | ||||||
|  |    * setgid before calling issetugid() should still be tainted | ||||||
|  |    */ | ||||||
|  |   system("chmod 4755 setuid"); | ||||||
|  |   if (execute("setuid", "06755") != 1) e(3); | ||||||
|  | 
 | ||||||
|  |   /* When we exec a new process that has setgid set, and which upon
 | ||||||
|  |    * execution forks, the forked child should also be tainted */ | ||||||
|  |   system("chmod 4755 setuidfork"); | ||||||
|  |   if (execute("setuidfork", "0000") != 1) e(4); | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void test_setugid(void) | ||||||
|  | { | ||||||
|  | /* Execve a new process that has setuid and setgid bits set */ | ||||||
|  |   subtest = 5; | ||||||
|  | 
 | ||||||
|  |   /* When we exec a new process which has setugid set, that
 | ||||||
|  |    * process should be tainted. | ||||||
|  |    */ | ||||||
|  |   system("chmod 6755 setugid"); | ||||||
|  |   if (execute("setugid", "0000") != 1) e(1); | ||||||
|  | 
 | ||||||
|  |   /* When we exec a new process which has setugid set, but unsets those bits
 | ||||||
|  |    * before calling issetugid() should still be tainted | ||||||
|  |    */ | ||||||
|  |   system("chmod 6755 setugid"); | ||||||
|  |   if (execute("setugid", "0755") != 1) e(2); | ||||||
|  | 
 | ||||||
|  |   /* When we exec a new process that has setugid set, and which upon
 | ||||||
|  |    * execution forks, the forked child should also be tainted */ | ||||||
|  |   system("chmod 6755 setugidfork"); | ||||||
|  |   if (execute("setugidfork", "0000") != 1) e(4); | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void test_effugid(void) | ||||||
|  | { | ||||||
|  | /* Test taint status with different effective uid and gid */ | ||||||
|  |   pid_t childpid; | ||||||
|  |   int status; | ||||||
|  | 
 | ||||||
|  |   subtest = 6; | ||||||
|  | 
 | ||||||
|  |   /* Start with effective uid */ | ||||||
|  |   childpid = fork(); | ||||||
|  |   if (childpid == (pid_t) -1) e(1); | ||||||
|  |   else if (childpid == 0) { | ||||||
|  | 	/* We're the child */ | ||||||
|  | 
 | ||||||
|  | 	/* We should be tainted */ | ||||||
|  | 	if (issetugid() != 1) e(2); | ||||||
|  | 
 | ||||||
|  | 	/* Now execute a program without set{u,g}id; should not be tainted */ | ||||||
|  | 	system("chmod 755 nobits"); | ||||||
|  | 	if (execute("nobits", "0000") != 0) e(3); | ||||||
|  | 
 | ||||||
|  | 	/* Change effective uid into current+42 and try nobits again. This time
 | ||||||
|  | 	 * it should be tainted */ | ||||||
|  | 	if (seteuid(geteuid() + 42) != 0) e(4); | ||||||
|  | 	if (execute("nobits", "0000") != 1) e(5); | ||||||
|  | 	exit(EXIT_SUCCESS); | ||||||
|  |   } else { | ||||||
|  | 	/* We're the parent, wait for the child to finish */ | ||||||
|  | 	wait(&status); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   /* Now test effective gid */ | ||||||
|  |   childpid = fork(); | ||||||
|  |   if (childpid == (pid_t) -1) e(1); | ||||||
|  |   else if (childpid == 0) { | ||||||
|  | 	/* We're the child */ | ||||||
|  | 
 | ||||||
|  | 	/* We should be tainted */ | ||||||
|  | 	if (issetugid() != 1) e(2); | ||||||
|  | 
 | ||||||
|  | 	/* Now execute a program without set{u,g}id; should not be tainted */ | ||||||
|  | 	system("chmod 755 nobits"); | ||||||
|  | 	if (execute("nobits", "0000") != 0) e(3); | ||||||
|  | 
 | ||||||
|  | 	/* Change effective gid into current+42 and try nobits again. This time
 | ||||||
|  | 	 * it should be tainted */ | ||||||
|  | 	if (seteuid(getegid() + 42) != 0) e(4); | ||||||
|  | 	if (execute("nobits", "0000") != 1) e(5); | ||||||
|  | 	exit(EXIT_SUCCESS); | ||||||
|  |   } else { | ||||||
|  | 	/* We're the parent, wait for the child to finish */ | ||||||
|  | 	wait(&status); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void test_setnone(void) | ||||||
|  | { | ||||||
|  | /* Execve a new process that does not have setuid or setgid bits set */ | ||||||
|  |   subtest = 2; | ||||||
|  | 
 | ||||||
|  |   /* When we exec a new process which doesn't have set{u,g}id set, that
 | ||||||
|  |    * process should not be tainted */ | ||||||
|  |   system("chmod 755 nobits"); | ||||||
|  |   if (execute("nobits", "0000") != 0) e(2); | ||||||
|  | 
 | ||||||
|  |   /* When we exec a new process which doesn't have set{u,g}id set, but
 | ||||||
|  |    * sets them after execution, the process should still not be tainted | ||||||
|  |    */ | ||||||
|  |   system("chmod 755 nobits"); | ||||||
|  |   if (execute("nobits", "02755") != 0) e(4); | ||||||
|  |   system("chmod 755 nobits"); | ||||||
|  |   if (execute("nobits", "04755") != 0) e(3); | ||||||
|  |   system("chmod 755 nobits"); | ||||||
|  |   if (execute("nobits", "06755") != 0) e(5); | ||||||
|  | 
 | ||||||
|  |   /* When we exec a new process that doesn't have setugid set, and which upon
 | ||||||
|  |    * execution forks, the forked child should not be tainted either */ | ||||||
|  |   system("chmod 755 nobitsfork"); | ||||||
|  |   if (execute("nobitsfork", "0000") != 0) e(6); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void test_self(void) | ||||||
|  | { | ||||||
|  | /* We're supposed to be setuid. Verify. */ | ||||||
|  | 
 | ||||||
|  |   int status; | ||||||
|  |   pid_t childpid; | ||||||
|  | 
 | ||||||
|  |   subtest = 1; | ||||||
|  | 
 | ||||||
|  |   if (issetugid() != 1) e(1); | ||||||
|  |   childpid = fork(); | ||||||
|  |   if (childpid == -1) e(2); | ||||||
|  |   else if (childpid == 0) { | ||||||
|  | 	/* We're the child and should inherit the tainted status of the parent
 | ||||||
|  | 	 */ | ||||||
|  | 	if (issetugid() != 1) e(3); | ||||||
|  | 
 | ||||||
|  | 	/* Let's change to the bin user */ | ||||||
|  | 	if (setuid((uid_t) 2) != 0) e(4); | ||||||
|  | 	if (getuid() != (uid_t) 2) e(5); | ||||||
|  | 
 | ||||||
|  | 	/* At this point, taint status should not have changed. */ | ||||||
|  | 	if (issetugid() != 1) e(6); | ||||||
|  | 
 | ||||||
|  | 	exit(EXIT_SUCCESS); | ||||||
|  |   } else { | ||||||
|  | 	/* We're the parent. Wait for the child to finish */ | ||||||
|  | 	wait(&status); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void switch_to_su(void) | ||||||
|  | { | ||||||
|  |   subtest = 0; | ||||||
|  |   if (setuid(0) != 0) e(1); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int main(int argc, char **argv) | ||||||
|  | { | ||||||
|  |   start(60); | ||||||
|  |   system("cp ../t60a nobits"); | ||||||
|  |   system("cp ../t60a setgid"); | ||||||
|  |   system("cp ../t60a setuid"); | ||||||
|  |   system("cp ../t60a setugid"); | ||||||
|  |   system("cp ../t60b nobitsfork"); | ||||||
|  |   system("cp ../t60b setuidfork"); | ||||||
|  |   system("cp ../t60b setgidfork"); | ||||||
|  |   system("cp ../t60b setugidfork"); | ||||||
|  | 
 | ||||||
|  |   switch_to_su();	/* We have to be root to perform this test */ | ||||||
|  |   test_self(); | ||||||
|  |   test_setnone(); | ||||||
|  |   test_setuid(); | ||||||
|  |   test_setgid(); | ||||||
|  |   test_setugid(); | ||||||
|  |   test_effugid(); | ||||||
|  | 
 | ||||||
|  |   quit(); | ||||||
|  | 
 | ||||||
|  |   return(-1);	/* Never reached */ | ||||||
|  | } | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Thomas Veerman
						Thomas Veerman