diff --git a/Makefile b/Makefile index 300e4d8b6..83a53b84c 100644 --- a/Makefile +++ b/Makefile @@ -31,6 +31,11 @@ DIRS:=applets archival archival/libunarchive coreutils console-tools \ networking/libiproute networking/udhcp procps loginutils shell \ sysklogd util-linux libbb libpwdgrp coreutils/libcoreutils +ifeq ($(strip $(CONFIG_SELINUX)),y) +CFLAGS += -I/usr/include/selinux +LIBRARIES += -lsecure +endif + ifeq ($(strip $(HAVE_DOT_CONFIG)),y) all: busybox busybox.links #doc diff --git a/coreutils/id.c b/coreutils/id.c index 9b2d60dc7..971e7cdad 100644 --- a/coreutils/id.c +++ b/coreutils/id.c @@ -28,9 +28,13 @@ #include #include #include +#ifdef CONFIG_SELINUX +#include +#include +#endif -#define NO_GROUP 1 -#define NO_USER 2 +#define JUST_USER 1 +#define JUST_GROUP 2 #define PRINT_REAL 4 #define NAME_NOT_NUMBER 8 @@ -40,10 +44,13 @@ extern int id_main(int argc, char **argv) long pwnam, grnam; int uid, gid; int flags; +#ifdef CONFIG_SELINUX + int is_flask_enabled_flag = is_flask_enabled(); +#endif flags = bb_getopt_ulflags(argc, argv, "ugrn"); - if (((flags & (NO_USER | NO_GROUP)) == (NO_USER | NO_GROUP)) + if (((flags & (JUST_USER | JUST_GROUP)) == (JUST_USER | JUST_GROUP)) || (argc > optind + 1) ) { bb_show_usage(); @@ -67,9 +74,9 @@ extern int id_main(int argc, char **argv) pwnam=my_getpwnam(user); grnam=my_getgrnam(group); - if (flags & (NO_GROUP | NO_USER)) { + if (flags & (JUST_GROUP | JUST_USER)) { char *s = group; - if (flags & NO_GROUP) { + if (flags & JUST_USER) { s = user; grnam = pwnam; } @@ -79,7 +86,24 @@ extern int id_main(int argc, char **argv) printf("%ld\n", grnam); } } else { +#ifdef CONFIG_SELINUX + printf("uid=%ld(%s) gid=%ld(%s)", pwnam, user, grnam, group); + if(is_flask_enabled_flag) + { + security_id_t mysid = getsecsid(); + char context[80]; + int len = sizeof(context); + context[0] = '\0'; + if(security_sid_to_context(mysid, context, &len)) + strcpy(context, "unknown"); + printf(" context=%s\n", context); + } + else + printf("\n"); +#else printf("uid=%ld(%s) gid=%ld(%s)\n", pwnam, user, grnam, group); +#endif + } bb_fflush_stdout_and_exit(0); diff --git a/coreutils/ls.c b/coreutils/ls.c index 4a4956611..6245361e9 100644 --- a/coreutils/ls.c +++ b/coreutils/ls.c @@ -62,6 +62,11 @@ enum { #include #include #include "busybox.h" +#ifdef CONFIG_SELINUX +#include +#include +#include +#endif #ifdef CONFIG_FEATURE_LS_TIMESTAMPS #include @@ -89,14 +94,15 @@ enum { #define LIST_NLINKS (1U<<3) #define LIST_ID_NAME (1U<<4) #define LIST_ID_NUMERIC (1U<<5) -#define LIST_SIZE (1U<<6) -#define LIST_DEV (1U<<7) -#define LIST_DATE_TIME (1U<<8) -#define LIST_FULLTIME (1U<<9) -#define LIST_FILENAME (1U<<10) -#define LIST_SYMLINK (1U<<11) -#define LIST_FILETYPE (1U<<12) -#define LIST_EXEC (1U<<13) +#define LIST_CONTEXT (1U<<6) +#define LIST_SIZE (1U<<7) +#define LIST_DEV (1U<<8) +#define LIST_DATE_TIME (1U<<9) +#define LIST_FULLTIME (1U<<10) +#define LIST_FILENAME (1U<<11) +#define LIST_SYMLINK (1U<<12) +#define LIST_FILETYPE (1U<<13) +#define LIST_EXEC (1U<<14) #define LIST_MASK ((LIST_EXEC << 1) - 1) @@ -179,6 +185,9 @@ struct dnode { /* the basic node */ char *name; /* the dir entry name */ char *fullname; /* the dir entry name */ struct stat dstat; /* the file stat info */ +#ifdef CONFIG_SELINUX + security_id_t sid; +#endif struct dnode *next; /* point at the next node */ }; typedef struct dnode dnode_t; @@ -189,6 +198,10 @@ static int list_single(struct dnode *); static unsigned int all_fmt; +#ifdef CONFIG_SELINUX +static int is_flask_enabled_flag; +#endif + #ifdef CONFIG_FEATURE_AUTOWIDTH static unsigned short terminal_width = TERMINAL_WIDTH; static unsigned short tabstops = COLUMN_GAP; @@ -203,26 +216,49 @@ static struct dnode *my_stat(char *fullname, char *name) { struct stat dstat; struct dnode *cur; +#ifdef CONFIG_SELINUX + security_id_t sid; +#endif + int rc; #ifdef CONFIG_FEATURE_LS_FOLLOWLINKS if (all_fmt & FOLLOW_LINKS) { - if (stat(fullname, &dstat)) { +#ifdef CONFIG_SELINUX + if(is_flask_enabled_flag) + rc = stat_secure(fullname, &dstat, &sid); + else +#endif + rc = stat(fullname, &dstat); + if(rc) + { bb_perror_msg("%s", fullname); status = EXIT_FAILURE; return 0; } } else #endif - if (lstat(fullname, &dstat)) { - bb_perror_msg("%s", fullname); - status = EXIT_FAILURE; - return 0; + { +#ifdef CONFIG_SELINUX + if(is_flask_enabled_flag) + rc = lstat_secure(fullname, &dstat, &sid); + else +#endif + rc = lstat(fullname, &dstat); + if(rc) + { + bb_perror_msg("%s", fullname); + status = EXIT_FAILURE; + return 0; + } } cur = (struct dnode *) xmalloc(sizeof(struct dnode)); cur->fullname = fullname; cur->name = name; cur->dstat = dstat; +#ifdef CONFIG_SELINUX + cur->sid = sid; +#endif return cur; } @@ -451,6 +487,9 @@ static void showfiles(struct dnode **dn, int nfiles) /* find the longest file name- use that as the column width */ for (i = 0; i < nfiles; i++) { int len = strlen(dn[i]->name) + +#ifdef CONFIG_SELINUX + ((all_fmt & LIST_CONTEXT) ? 33 : 0) + +#endif ((all_fmt & LIST_INO) ? 8 : 0) + ((all_fmt & LIST_BLOCKS) ? 5 : 0); if (column_width < len) @@ -694,6 +733,21 @@ static int list_single(struct dnode *dn) } column += 13; break; +#endif +#ifdef CONFIG_SELINUX + case LIST_CONTEXT: + { + char context[64]; + int len = sizeof(context); + if(security_sid_to_context(dn->sid, context, &len)) + { + strcpy(context, "unknown"); + len = 7; + } + printf("%-32s ", context); + column += MAX(33, len); + } + break; #endif case LIST_FILENAME: #ifdef CONFIG_FEATURE_LS_COLOR @@ -774,6 +828,9 @@ static const char ls_opts[] = "1AaCdgilnsx" "h" #endif "k" +#ifdef CONFIG_SELINUX + "K" +#endif #ifdef CONFIG_FEATURE_AUTOWIDTH "T:w:" #endif @@ -834,7 +891,12 @@ static const unsigned opt_flags[] = { #ifdef CONFIG_FEATURE_HUMAN_READABLE LS_DISP_HR, /* h */ #endif +#ifndef CONFIG_SELINUX 0, /* k - ingored */ +#else + LIST_CONTEXT, /* k */ + LIST_MODEBITS|LIST_NLINKS|LIST_CONTEXT|LIST_SIZE|LIST_DATE_TIME, /* K */ +#endif }; @@ -849,6 +911,9 @@ extern int ls_main(int argc, char **argv) int opt; int oi, ac; char **av; +#ifdef CONFIG_SELINUX + is_flask_enabled_flag = is_flask_enabled(); +#endif #ifdef CONFIG_FEATURE_AUTOWIDTH struct winsize win = { 0, 0, 0, 0 }; @@ -911,6 +976,9 @@ extern int ls_main(int argc, char **argv) if (flags & TIME_MASK_TRIGGER) { all_fmt &= ~TIME_MASK; } + if (flags & LIST_CONTEXT) { + all_fmt |= STYLE_SINGLE; + } #ifdef CONFIG_FEATURE_HUMAN_READABLE if (opt == 'l') { all_fmt &= ~LS_DISP_HR; diff --git a/include/libbb.h b/include/libbb.h index 7b3ac4b85..edb8a6ed4 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -39,6 +39,9 @@ #include #include "config.h" +#ifdef CONFIG_SELINUX +#include +#endif #include "pwd_.h" #include "grp_.h" @@ -394,7 +397,11 @@ void bb_xasprintf(char **string_ptr, const char *format, ...) __attribute__ ((fo #define FAIL_DELAY 3 extern void change_identity ( const struct passwd *pw ); -extern void run_shell ( const char *shell, int loginshell, const char *command, const char **additional_args ); +extern void run_shell ( const char *shell, int loginshell, const char *command, const char **additional_args +#ifdef CONFIG_SELINUX + , security_id_t sid +#endif +); extern int run_parts(char **args, const unsigned char test_mode); extern int restricted_shell ( const char *shell ); extern void setup_environment ( const char *shell, int loginshell, int changeenv, const struct passwd *pw ); @@ -425,7 +432,11 @@ typedef struct { char short_cmd[16]; } procps_status_t; -extern procps_status_t * procps_scan(int save_user_arg0); +extern procps_status_t * procps_scan(int save_user_arg0 +#ifdef CONFIG_SELINUX + , int use_selinux, security_id_t *sid +#endif +); extern unsigned short compare_string_array(const char *string_array[], const char *key); extern int my_query_module(const char *name, int which, void **buf, size_t *bufsize, size_t *ret); diff --git a/include/usage.h b/include/usage.h index 701b40daa..e0cfa7d2f 100644 --- a/include/usage.h +++ b/include/usage.h @@ -882,6 +882,12 @@ "\t-u\tthe hardware clock is kept in coordinated universal time\n" \ "\t-l\tthe hardware clock is kept in local time" +#ifdef CONFIG_SELINUX +#define USAGE_SELINUX(a, b) a +#else +#define USAGE_SELINUX(a, b) b +#endif + #define id_trivial_usage \ "[OPTIONS]... [USERNAME]" #define id_full_usage \ @@ -889,6 +895,7 @@ "Options:\n" \ "\t-g\tprints only the group ID\n" \ "\t-u\tprints only the user ID\n" \ + USAGE_SELINUX("\t-c\tprints only the security context\n", "") \ "\t-n\tprint a name instead of a number (with for -ug)\n" \ "\t-r\tprints the real user ID instead of the effective ID (with -ug)" #define id_example_usage \ @@ -1347,7 +1354,7 @@ #define USAGE_AUTOWIDTH(a) #endif #define ls_trivial_usage \ - "[-1Aa" USAGE_LS_TIMESTAMPS("c") "Cd" USAGE_LS_TIMESTAMPS("e") USAGE_LS_FILETYPES("F") "iln" USAGE_LS_FILETYPES("p") USAGE_LS_FOLLOWLINKS("L") USAGE_LS_RECURSIVE("R") USAGE_LS_SORTFILES("rS") "s" USAGE_AUTOWIDTH("T") USAGE_LS_TIMESTAMPS("tu") USAGE_LS_SORTFILES("v") USAGE_AUTOWIDTH("w") "x" USAGE_LS_SORTFILES("X") USAGE_HUMAN_READABLE("h") USAGE_NOT_HUMAN_READABLE("") "k] [filenames...]" + "[-1Aa" USAGE_LS_TIMESTAMPS("c") "Cd" USAGE_LS_TIMESTAMPS("e") USAGE_LS_FILETYPES("F") "iln" USAGE_LS_FILETYPES("p") USAGE_LS_FOLLOWLINKS("L") USAGE_LS_RECURSIVE("R") USAGE_LS_SORTFILES("rS") "s" USAGE_AUTOWIDTH("T") USAGE_LS_TIMESTAMPS("tu") USAGE_LS_SORTFILES("v") USAGE_AUTOWIDTH("w") "x" USAGE_LS_SORTFILES("X") USAGE_HUMAN_READABLE("h") USAGE_NOT_HUMAN_READABLE("") "k" USAGE_SELINUX("K", "") "] [filenames...]" #define ls_full_usage \ "List directory contents\n\n" \ "Options:\n" \ @@ -1377,8 +1384,7 @@ USAGE_LS_SORTFILES("\t-X\tsort the listing by extension\n") \ USAGE_HUMAN_READABLE( \ "\t-h\tprint sizes in human readable format (e.g., 1K 243M 2G )\n" \ - "\t-k\tprint sizes in kilobytes(default)") USAGE_NOT_HUMAN_READABLE( \ - "\t-k\tprint sizes in kilobytes(compatibility)") + USAGE_SELINUX("\t-k\tprint security context\n\t-K\tprint security context in long format\n", "") #define lsmod_trivial_usage \ "" @@ -1786,7 +1792,8 @@ "" #define ps_full_usage \ "Report process status\n" \ - "\nThis version of ps accepts no options." + USAGE_SELINUX("\nOptions:\n\t-c\tshow SE Linux context", "\nThis version of ps accepts no options.") + #define ps_example_usage \ "$ ps\n" \ " PID Uid Gid State Command\n" \ diff --git a/libbb/find_pid_by_name.c b/libbb/find_pid_by_name.c index b6602b942..b8490b724 100644 --- a/libbb/find_pid_by_name.c +++ b/libbb/find_pid_by_name.c @@ -41,7 +41,11 @@ extern long* find_pid_by_name( const char* pidName) procps_status_t * p; pidList = xmalloc(sizeof(long)); +#ifdef CONFIG_SELINUX + while ((p = procps_scan(0, 0, NULL)) != 0) { +#else while ((p = procps_scan(0)) != 0) { +#endif if (strcmp(p->short_cmd, pidName) == 0) { pidList=xrealloc( pidList, sizeof(long) * (i+2)); pidList[i++]=p->pid; diff --git a/libbb/procps.c b/libbb/procps.c index 7df071869..44103fae8 100644 --- a/libbb/procps.c +++ b/libbb/procps.c @@ -16,7 +16,11 @@ #include "libbb.h" -extern procps_status_t * procps_scan(int save_user_arg0) +extern procps_status_t * procps_scan(int save_user_arg0 +#ifdef CONFIG_SELINUX + , int use_selinux , security_id_t *sid +#endif + ) { static DIR *dir; struct dirent *entry; @@ -53,6 +57,14 @@ extern procps_status_t * procps_scan(int save_user_arg0) sprintf(status, "/proc/%d/stat", pid); if((fp = fopen(status, "r")) == NULL) continue; +#ifdef CONFIG_SELINUX + if(use_selinux) + { + if(fstat_secure(fileno(fp), &sb, sid)) + continue; + } + else +#endif if(fstat(fileno(fp), &sb)) continue; my_getpwuid(curstatus.user, sb.st_uid); diff --git a/libbb/run_shell.c b/libbb/run_shell.c index 49e8a76c2..4855d763e 100644 --- a/libbb/run_shell.c +++ b/libbb/run_shell.c @@ -36,14 +36,20 @@ #include #include #include "libbb.h" - +#ifdef CONFIG_SELINUX +#include +#endif /* Run SHELL, or DEFAULT_SHELL if SHELL is empty. If COMMAND is nonzero, pass it to the shell with the -c option. If ADDITIONAL_ARGS is nonzero, pass it to the shell as more arguments. */ -void run_shell ( const char *shell, int loginshell, const char *command, const char **additional_args ) +void run_shell ( const char *shell, int loginshell, const char *command, const char **additional_args +#ifdef CONFIG_SELINUX + , security_id_t sid +#endif +) { const char **args; int argno = 1; @@ -71,6 +77,11 @@ void run_shell ( const char *shell, int loginshell, const char *command, const c args [argno++] = *additional_args; } args [argno] = 0; +#ifdef CONFIG_SELINUX + if(sid) + execve_secure(shell, (char **) args, environ, sid); + else +#endif execv ( shell, (char **) args ); bb_perror_msg_and_die ( "cannot run %s", shell ); } diff --git a/loginutils/login.c b/loginutils/login.c index e239f421c..741d15c93 100644 --- a/loginutils/login.c +++ b/loginutils/login.c @@ -16,7 +16,12 @@ #include #include "busybox.h" - +#ifdef CONFIG_SELINUX +#include +#include +#include +#include +#endif #ifdef CONFIG_FEATURE_U_W_TMP // import from utmp.c @@ -73,6 +78,10 @@ extern int login_main(int argc, char **argv) int opt_fflag = 0; char *opt_host = 0; int alarmstarted = 0; +#ifdef CONFIG_SELINUX + int flask_enabled = is_flask_enabled(); + security_id_t sid = 0, old_tty_sid, new_tty_sid; +#endif username[0]=0; amroot = ( getuid ( ) == 0 ); @@ -217,6 +226,36 @@ auth_ok: #ifdef CONFIG_FEATURE_U_W_TMP setutmp ( username, tty ); #endif +#ifdef CONFIG_SELINUX + if (flask_enabled) + { + struct stat st; + + if (get_default_sid(username, 0, &sid)) + { + fprintf(stderr, "Unable to get SID for %s\n", username); + exit(1); + } + if (stat_secure(tty, &st, &old_tty_sid)) + { + fprintf(stderr, "stat_secure(%.100s) failed: %.100s\n", tty, strerror(errno)); + return EXIT_FAILURE; + } + if (security_change_sid (sid, old_tty_sid, SECCLASS_CHR_FILE, &new_tty_sid) != 0) + { + fprintf(stderr, "security_change_sid(%.100s) failed: %.100s\n", tty, strerror(errno)); + return EXIT_FAILURE; + } + if(chsid(tty, new_tty_sid) != 0) + { + fprintf(stderr, "chsid(%.100s, %d) failed: %.100s\n", tty, new_tty_sid, strerror(errno)); + return EXIT_FAILURE; + } + } + else + sid = 0; +#endif + if ( *tty != '/' ) snprintf ( full_tty, sizeof( full_tty ) - 1, "/dev/%s", tty); else @@ -239,7 +278,11 @@ auth_ok: if ( pw-> pw_uid == 0 ) syslog ( LOG_INFO, "root login %s\n", fromhost ); - run_shell ( pw-> pw_shell, 1, 0, 0 ); /* exec the shell finally. */ + run_shell ( pw-> pw_shell, 1, 0, 0 +#ifdef CONFIG_SELINUX + , sid +#endif + ); /* exec the shell finally. */ return EXIT_FAILURE; } diff --git a/loginutils/su.c b/loginutils/su.c index 5e40cf2e4..85f5cbe7b 100644 --- a/loginutils/su.c +++ b/loginutils/su.c @@ -156,7 +156,11 @@ int su_main ( int argc, char **argv ) change_identity ( pw ); setup_environment ( opt_shell, opt_loginshell, !opt_preserve, pw ); - run_shell ( opt_shell, opt_loginshell, opt_command, (const char**)opt_args ); + run_shell ( opt_shell, opt_loginshell, opt_command, (const char**)opt_args +#ifdef CONFIG_SELINUX + , 0 +#endif + ); return EXIT_FAILURE; } diff --git a/procps/ps.c b/procps/ps.c index 5ccac7a95..691f490c7 100644 --- a/procps/ps.c +++ b/procps/ps.c @@ -31,6 +31,11 @@ #include #include #include "busybox.h" +#ifdef CONFIG_SELINUX +#include +#include +#include /* for is_flask_enabled() */ +#endif static const int TERMINAL_WIDTH = 79; /* not 80 in case terminal has linefold bug */ @@ -47,6 +52,13 @@ extern int ps_main(int argc, char **argv) #define terminal_width TERMINAL_WIDTH #endif +#ifdef CONFIG_SELINUX + int use_selinux = 0; + security_id_t sid; + if(is_flask_enabled() && argv[1] && !strcmp(argv[1], "-c") ) + use_selinux = 1; +#endif + #ifdef CONFIG_FEATURE_AUTOWIDTH ioctl(fileno(stdout), TIOCGWINSZ, &win); @@ -54,10 +66,31 @@ extern int ps_main(int argc, char **argv) terminal_width = win.ws_col - 1; #endif +#ifdef CONFIG_SELINUX + if(use_selinux) + printf(" PID Context Stat Command\n"); + else +#endif printf(" PID Uid VmSize Stat Command\n"); +#ifdef CONFIG_SELINUX + while ((p = procps_scan(1, use_selinux, &sid)) != 0) { +#else while ((p = procps_scan(1)) != 0) { +#endif char *namecmd = p->cmd; +#ifdef CONFIG_SELINUX + if(use_selinux) + { + char sbuf[128]; + len = sizeof(sbuf); + if(security_sid_to_context(sid, (security_context_t)&sbuf, &len)) + strcpy(sbuf, "unknown"); + + len = printf("%5d %-32s %s ", p->pid, sbuf, p->state); + } + else +#endif if(p->rss == 0) len = printf("%5d %-8s %s ", p->pid, p->user, p->state); else diff --git a/procps/top.c b/procps/top.c index b70a42a72..2e1bd3286 100644 --- a/procps/top.c +++ b/procps/top.c @@ -501,7 +501,11 @@ int top_main(int argc, char **argv) /* read process IDs & status for all the processes */ procps_status_t * p; +#ifdef CONFIG_SELINUX + while ((p = procps_scan(0, 0, NULL) ) != 0) { +#else while ((p = procps_scan(0)) != 0) { +#endif int n = ntop; top = xrealloc(top, (++ntop)*sizeof(procps_status_t)); diff --git a/sysdeps/linux/Config.in b/sysdeps/linux/Config.in index 70dd2ca5e..2e9ddc382 100644 --- a/sysdeps/linux/Config.in +++ b/sysdeps/linux/Config.in @@ -106,6 +106,13 @@ config CONFIG_FEATURE_SUID_CONFIG_QUIET help Please submit a patch to add help text for this item. +config CONFIG_SELINUX + bool "Support NSA Security Enhanced Linux" + default n + help + Enable support for SE Linux in applets ls, ps, and id. Also provide + the option of compiling in SE Linux applets. + endmenu menu 'Build Options'