Originally Posted by
CornedBee
The suid programs may run on a higher privilege level than you (if they suid to root). It shouldn't be possible to kill them.
That doesn't answer my question....
Here is the entire program. If a person has a regular user account on OpenBSD 4.1, then this program will kill programs that suid to root. I don't think this will compile on Linux or FreeBSD.
Code:
#include <sys/types.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/sysctl.h>
#include <sys/user.h>
#include <utmp.h>
#include <paths.h>
#include <limits.h>
#include <stdio.h>
#include <unistd.h>
#include <pwd.h>
#include <fcntl.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include <signal.h>
/*If you get to this number, then you really shouldn't be using this program*/
#define MAX_USERS 19
typedef struct {
uid_t uid;
dev_t dev;
pid_t pid;
struct utmp in_login;
}uinfo_t;
uinfo_t uinfo[MAX_USERS];
int get_user_info(char *);
void get_uid(char *, uinfo_t *);
int get_my_pid(uinfo_t *);
struct passwd *get_my_name(void);
int compare (const void *, const void *);
void find_sessions_to_kill(int );
void kill_sessions(int n);
/*Fill in the login fields*/
int
get_user_info(char *user)
{
static struct utmp logins;
static int fd;
static char tty[MAXPATHLEN];
static int n;
n = 0;
if(( fd = open(_PATH_UTMP, O_RDONLY)) < 0){
return -1;
}
while(read(fd, &logins, sizeof(logins)) == sizeof(logins)) {
if (strncmp(logins.ut_name, user, UT_NAMESIZE)) {
continue;
}
(void)snprintf(tty, sizeof(tty), "%s/%s", _PATH_DEV,
logins.ut_line);
uinfo[n].in_login = logins;
get_uid(tty, &uinfo[n++]);
}
close(fd);
return n;
}
/*Fill in the uid field*/
void
get_uid(char *tty, uinfo_t *uinfo)
{
static struct stat s;
static int i;
if(stat(tty, &s) < 0){
fprintf(stderr, "no tty\n");
return;
}
uinfo->dev = s.st_rdev;
uinfo->uid = s.st_uid;
if(get_my_pid(&uinfo[i++])){
fprintf(stderr, "can't get pids\n");
return;
}
}
/*Fill in the pid field. */
int
get_my_pid(uinfo_t *tty)
{
int mib[4];
static int i;
size_t len;
struct kinfo_proc *p;
mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
mib[2] = KERN_PROC_TTY;
mib[3] = uinfo[i].dev;
len = 0;
if (sysctl(mib, sizeof(mib)/sizeof(int), NULL , &len, NULL, 0) == -1)
{
perror("sysctl test");
return 1;
}
p =(struct kinfo_proc *)malloc(len);
if (sysctl(mib, sizeof(mib)/sizeof(int), p, &len, NULL, 0) == -1)
{
perror("sysctl real");
return 1;
}
uinfo[i++].pid = p->kp_proc.p_pid;
free(p);
return 0;
}
struct passwd *
get_my_name(void)
{
struct passwd *pw;
/*I'm not that sure of the difference between guest and regular accounts.*/
if((pw = getpwnam(getlogin()))== NULL ){
return NULL;
}
return pw;
}
int
compare (const void *a, const void *b)
{
/*const struct utmp *ma = *(const struct utmp *const*)a;
const struct utmp *mb = *(const struct utmp *const*)b;*/
const struct utmp *ma = a;
const struct utmp *mb = b;
int32_t time1, time2;
time1 = ma->ut_time;
time2 = mb->ut_time;
if(time1 < time2)
return -1;
else if(time1 > time2)
return 1;
else
return 0;
}
void
print_session(int count)
{
int i;
for(i = 0; i < count; i++)
printf("name: %s, tty: %s\n", uinfo[i].in_login.ut_name, uinfo[i].in_login.ut_line);
}
void
find_sessions_to_kill(int count){
qsort(uinfo,
count,
sizeof(struct utmp),
compare
);
print_session(count);
kill_sessions(count);
}
/*I only want to kill interactive sessions */
void
kill_sessions(int count)
{
int i;
int j;
int max;
max = 20;
/*This does properly kill processes that forked suid programs*/
for(i = (count-1); i > 0; i--){
(void)kill(uinfo[i].pid, SIGHUP);
/*if((kill(uinfo[i].pid, 0)) == -1 && errno == ESRCH)
break;*/
}
}
int
main(void)
{
/*add error checking later on */
struct passwd *name;
int n;
if((name = get_my_name()) == NULL)
exit(1);
if((n=get_user_info(name->pw_name)) < 0)
exit(1);
if(n == 1 || n > MAX_USERS)
exit(1);
find_sessions_to_kill(n);
exit(0);
}
Again, if process B would execute a suid program, how would I kill both the suid program and the shell? I'm assuming I would have to test if the process is still alive. Ie, use something like
Code:
if((kill(uinfo[i].pid, 0)) == -1 && errno == ESRCH)
The problem is that I don't know how many suid programs process B would be executing at once.