Added SELinux support

Mostly backported from rpm-4.8
This commit is contained in:
Mikhail Efremov 2010-03-31 19:36:41 +04:00 committed by Dmitry V. Levin
parent df21cab192
commit f92be4b40e
17 changed files with 178 additions and 16 deletions

View File

@ -638,6 +638,31 @@ if test $withval = yes ; then
LIBS="$LIBS -ldmalloc"
fi
WITH_SELINUX_LIB=
AC_ARG_WITH(selinux, [AS_HELP_STRING([--with-selinux],[build with selinux support])],
[case "$with_selinux" in
yes|no) ;;
*) AC_MSG_ERROR([invalid argument to --with-selinux])
;;
esac],
[with_selinux=no])
AS_IF([test "$with_selinux" = yes],[
AC_CHECK_HEADER([selinux/selinux.h],[
AC_CHECK_LIB(selinux,[is_selinux_enabled],[with_selinux=yes],[
AC_MSG_ERROR([--with-selinux given, but libselinux not found])])
],[
AC_MSG_ERROR([--with-selinux given, but selinux/selinux.h not found])
])
])
AS_IF([test "$with_selinux" = yes],[
AC_DEFINE(WITH_SELINUX, 1, [Build with selinux support?])
WITH_SELINUX_LIB="-lselinux"
])
AC_SUBST(WITH_SELINUX_LIB)
AM_CONDITIONAL(SELINUX,[test "$with_selinux" = yes])
AC_CHECK_FUNCS(setlocale)
dnl XXX Solaris <= 2.6 only permits 8 chars in password.

View File

@ -35,7 +35,7 @@ librpm_la_SOURCES = \
signature.c stringbuf.c transaction.c \
verify.c
librpm_la_LDFLAGS = -release @VERSION@
librpm_la_LIBADD = $(top_builddir)/rpmdb/librpmdb.la $(top_builddir)/rpmio/librpmio.la @LIBPOPT@
librpm_la_LIBADD = $(top_builddir)/rpmdb/librpmdb.la $(top_builddir)/rpmio/librpmio.la @LIBPOPT@ @WITH_SELINUX_LIB@
librpm_la_DEPENDENCIES = $(top_builddir)/rpmdb/librpmdb.la $(top_builddir)/rpmio/librpmio.la
getdate.c: getdate.y

View File

@ -212,6 +212,7 @@ const char * cpioStrerror(int rc)
case CPIOERR_READLINK_FAILED: s = "readlink"; break;
case CPIOERR_READ_FAILED: s = "read"; break;
case CPIOERR_COPY_FAILED: s = "copy"; break;
case CPIOERR_LSETFCON_FAILED: s = "lsetfilecon"; break;
case CPIOERR_HDR_SIZE: s = _("Header size too big"); break;
case CPIOERR_UNKNOWN_FILETYPE: s = _("Unknown file type"); break;

View File

@ -46,13 +46,14 @@ enum cpioErrorReturns {
CPIOERR_READLINK_FAILED = (19 | CPIOERR_CHECK_ERRNO),
CPIOERR_READ_FAILED = (20 | CPIOERR_CHECK_ERRNO),
CPIOERR_COPY_FAILED = (21 | CPIOERR_CHECK_ERRNO),
CPIOERR_HDR_SIZE = (22 ),
CPIOERR_HDR_TRAILER = (23 ),
CPIOERR_UNKNOWN_FILETYPE= (24 ),
CPIOERR_MISSING_HARDLINK= (25 ),
CPIOERR_MD5SUM_MISMATCH = (26 ),
CPIOERR_INTERNAL = (27 ),
CPIOERR_UNMAPPED_FILE = (28 )
CPIOERR_LSETFCON_FAILED = (22 | CPIOERR_CHECK_ERRNO),
CPIOERR_HDR_SIZE = (23 ),
CPIOERR_HDR_TRAILER = (24 ),
CPIOERR_UNKNOWN_FILETYPE= (25 ),
CPIOERR_MISSING_HARDLINK= (26 ),
CPIOERR_MD5SUM_MISMATCH = (27 ),
CPIOERR_INTERNAL = (28 ),
CPIOERR_UNMAPPED_FILE = (29 )
};
/** \ingroup payload

View File

@ -261,6 +261,8 @@ rpmTransactionSet rpmtransCreateSet(rpmdb rpmdb, const char * rootDir)
ts->orderCount = 0;
ts->order = NULL;
ts->selinuxEnabled = is_selinux_enabled() > 0;
return ts;
}

View File

@ -120,6 +120,7 @@ struct rpmTransactionSet_s {
/*@only@*/ const char * currDir;/*!< Current working directory. */
/*@null@*/ FD_t scriptFd; /*!< Scriptlet stdout/stderr. */
int id; /*!< Transaction id. */
int selinuxEnabled; /*!< Is SE linux enabled? */
} ;
/** \ingroup rpmdep

View File

@ -518,6 +518,26 @@ int fsmTeardown(FSM_t fsm) {
/*@=nullstate@*/
}
static int fsmMapFContext(FSM_t fsm)
{
rpmTransactionSet ts = fsmGetTs(fsm);
struct stat * st;
st = &fsm->sb;
/*
* Find file security context (if not disabled).
*/
fsm->fcontext = NULL;
if (ts != NULL && !(ts->transFlags & RPMTRANS_FLAG_NOCONTEXTS)) {
security_context_t scon = NULL;
if (matchpathcon(fsm->path, st->st_mode, &scon) == 0 && scon != NULL) {
fsm->fcontext = scon;
}
}
return 0;
}
int fsmMapPath(FSM_t fsm)
{
TFI_t fi = fsmGetFi(fsm); /* XXX const except for fstates */
@ -1140,10 +1160,26 @@ static int fsmMkdirs(/*@special@*/ FSM_t fsm)
*te = '\0';
st->st_mode = S_IFDIR | (fi->dperms & 07777);
rc = fsmStage(fsm, FSM_MKDIR);
if (!rc)
rpmMessage(RPMMESS_DEBUG,
_("%s directory created with perms %04o.\n"),
fsm->path, (unsigned)(st->st_mode & 07777));
if (!rc) {
/* XXX FIXME? only new dir will have context set. */
/* Get file security context from patterns. */
rc = fsmMapFContext(fsm);
if (!rc && fsm->fcontext)
rc = fsmStage(fsm, FSM_LSETFCON);
if (fsm->fcontext == NULL)
rpmMessage(RPMMESS_DEBUG,
_("%s directory created with perms %04o.\n"),
fsm->path, (unsigned)(st->st_mode & 07777));
else {
rpmMessage(RPMMESS_DEBUG,
_("%s directory created with perms %04o, context %s.\n"),
fsm->path, (unsigned)(st->st_mode & 07777),
fsm->fcontext);
freecon(fsm->fcontext);
fsm->fcontext = NULL;
}
}
*te = '/';
}
if (rc)
@ -1743,6 +1779,17 @@ if (!(fsm->mapFlags & CPIO_ALL_HARDLINKS)) break;
}
fsm->opath = _free(fsm->opath);
}
/*
* Set file security context (if not disabled).
*/
if (!rc && !getuid()) {
rc = fsmMapFContext(fsm);
if (!rc) {
rc = fsmStage(fsm, FSM_LSETFCON);
freecon(fsm->fcontext);
}
fsm->fcontext = NULL;
}
if (S_ISLNK(st->st_mode)) {
if (!rc && !getuid())
rc = fsmStage(fsm, FSM_LCHOWN);
@ -1888,6 +1935,19 @@ if (!(fsm->mapFlags & CPIO_ALL_HARDLINKS)) break;
fsm->path, (rc < 0 ? strerror(errno) : ""));
if (rc < 0) rc = CPIOERR_RMDIR_FAILED;
break;
case FSM_LSETFCON:
if (fsm->fcontext == NULL
|| *fsm->fcontext == '\0'
|| !strcmp(fsm->fcontext, "<<none>>"))
break;
rc = lsetfilecon(fsm->path, fsm->fcontext);
if (_fsm_debug && (stage & FSM_SYSCALL))
rpmMessage(RPMMESS_DEBUG, " %8s (%s, %s) %s\n", cur,
fsm->path, fsm->fcontext,
(rc < 0 ? strerror(errno) : ""));
if (rc < 0)
rc = (errno == EOPNOTSUPP ? 0 : CPIOERR_LSETFCON_FAILED);
break;
case FSM_CHOWN:
rc = chown(fsm->path, st->st_uid, st->st_gid);
if (_fsm_debug && (stage & FSM_SYSCALL))
@ -2175,6 +2235,7 @@ if (!(fsm->mapFlags & CPIO_ALL_HARDLINKS)) break;
case FSM_RENAME: return "Rename";
case FSM_MKDIR: return "Mkdir";
case FSM_RMDIR: return "rmdir";
case FSM_LSETFCON: return "lsetfcon";
case FSM_CHOWN: return "chown";
case FSM_LCHOWN: return "lchown";
case FSM_CHMOD: return "chmod";

View File

@ -66,6 +66,7 @@ typedef enum fileStage_e {
FSM_STAT = _fs(46),
FSM_READLINK= _fs(47),
FSM_CHROOT = _fs(48),
FSM_LSETFCON= _fs(49),
FSM_NEXT = _fd(65),
FSM_EAT = _fd(66),
@ -160,6 +161,7 @@ struct fsm_s {
/*@shared@*/ const char * dirName; /*!< File directory name. */
/*@shared@*/ const char * baseName; /*!< File base name. */
/*@shared@*/ const char * fmd5sum; /*!< File MD5 sum (NULL disables). */
security_context_t fcontext; /*!< File security context (NULL disables). */
unsigned fflags; /*!< File flags. */
fileAction action; /*!< File disposition. */
fileStage goal; /*!< Package state machine goal. */

View File

@ -160,6 +160,9 @@ struct poptOption rpmInstallPoptTable[] = {
N_("do not reorder package installation to satisfy dependencies"),
NULL},
{ "nocontexts", '\0', POPT_BIT_SET, &rpmIArgs.transFlags, RPMTRANS_FLAG_NOCONTEXTS,
N_("don't install file security contexts"), NULL},
{ "noscripts", '\0', POPT_BIT_SET, &rpmIArgs.transFlags,
(_noTransScripts|_noTransTriggers),
N_("do not execute package scriptlet(s)"), NULL },

View File

@ -882,7 +882,11 @@ static int runScript(PSM_t psm, Header h,
}
(void) chdir("/");
(void) umask(022);
xx = execv(argv[0], (char *const *)argv);
/* Permit libselinux to do the scriptlet exec. */
if (ts->selinuxEnabled)
xx = rpm_execcon(0, argv[0], (char *const *)argv, environ);
else
xx = execv(argv[0], (char *const *)argv);
break;
default:
break;

View File

@ -1401,7 +1401,7 @@ typedef enum rpmtransFlags_e {
/*@-enummemuse@*/
RPMTRANS_FLAG_KEEPOBSOLETE = (1 << 7), /*!< @todo Document. */
/*@=enummemuse@*/
// ___TRANS_FLAG_MULTILIB = (1 << 8), /*!< @todo Document. */
RPMTRANS_FLAG_NOCONTEXTS = (1 << 8), /*!< from --nocontexts */
RPMTRANS_FLAG_DIRSTASH = (1 << 9), /*!< from --dirstash */
RPMTRANS_FLAG_REPACKAGE = (1 << 10), /*!< from --repackage */

View File

@ -1528,6 +1528,17 @@ int rpmRunTransactions( rpmTransactionSet ts,
if (ts->transFlags & RPMTRANS_FLAG_JUSTDB)
ts->transFlags |= (_noTransScripts | _noTransTriggers);
/* if SELinux isn't enabled or init fails, don't bother... */
if (!ts->selinuxEnabled)
ts->transFlags |= RPMTRANS_FLAG_NOCONTEXTS;
if (!(ts->transFlags & RPMTRANS_FLAG_NOCONTEXTS)) {
const char *fn = rpmGetPath("%{?_install_file_context_path}", NULL);
if (matchpathcon_init(fn) == -1)
ts->transFlags |= RPMTRANS_FLAG_NOCONTEXTS;
fn = _free(fn);
}
ts->notify = notify;
ts->notifyData = notifyData;
/*@-assignexpose@*/
@ -2055,6 +2066,9 @@ assert(alp == fi->ap);
ts->flList = freeFl(ts, ts->flList);
ts->flEntries = 0;
if (!(ts->transFlags & RPMTRANS_FLAG_NOCONTEXTS))
matchpathcon_fini();
/*@-nullstate@*/
if (ourrc)
return -1;

View File

@ -294,6 +294,20 @@
# Note: The default value should be 0 for legacy compatibility.
%_unpackaged_files_terminate_build 0
# Desired selinux policy tree
%__policy_tree %(sed -rn 's;^[[:blank:]]*SELINUXTYPE=([^[:blank:]]+).*$;\\1;p' %{_sysconfdir}/selinux/config)
# Path to selinux file context patterns.
%__file_context_path /etc/selinux/%{__policy_tree}/contexts/files/file_contexts
#
# Path to selinux file context patterns used to set
# (or override package content) file contexts when installing.
#
# Undefined, missing or %{nil} will use package content (if available).
%_install_file_context_path %{__file_context_path}
#==============================================================================
# ---- Package version macro.
# The type of package to produce, for compatibility with legacy

View File

@ -983,6 +983,7 @@ void initrpm(void) {
REGISTER_ENUM(RPMTRANS_FLAG_NODOCS);
REGISTER_ENUM(RPMTRANS_FLAG_ALLFILES);
REGISTER_ENUM(RPMTRANS_FLAG_KEEPOBSOLETE);
REGISTER_ENUM(RPMTRANS_FLAG_NOCONTEXTS);
REGISTER_ENUM(RPMPROB_FILTER_IGNOREOS);
REGISTER_ENUM(RPMPROB_FILTER_IGNOREARCH);

View File

@ -26,7 +26,7 @@ librpmdb_la_SOURCES = db3.c \
dbconfig.c hdrNVR.c header.c fprint.c legacy.c merge.c poptDB.c \
rpmhash.c rpmdb.c rpmvercmp.c tagname.c tagtbl.c
librpmdb_la_LDFLAGS = -release @VERSION@
librpmdb_la_LIBADD = $(LIBDB) $(LIBELF) $(LIBPOPT) $(top_builddir)/rpmio/librpmio.la
librpmdb_la_LIBADD = $(LIBDB) $(LIBELF) $(LIBPOPT) $(top_builddir)/rpmio/librpmio.la @WITH_SELINUX_LIB@
librpmdb_la_DEPENDENCIES = $(top_builddir)/rpmio/librpmio.la
tagtbl.c: Makefile.am $(top_srcdir)/lib/rpmlib.h

View File

@ -3061,9 +3061,11 @@ static int rpmdbMoveDatabase(const char * prefix,
/*@modifies fileSystem @*/
{
int i;
struct stat st;
char * ofilename, * nfilename;
int rc = 0;
int xx;
int selinux = (is_selinux_enabled() > 0) && (matchpathcon_init(NULL) != -1);
i = strlen(olddbpath);
/*@-branchstate@*/
@ -3114,8 +3116,16 @@ static int rpmdbMoveDatabase(const char * prefix,
continue;
sprintf(nfilename, "%s/%s/%s", prefix, newdbpath, base);
(void)rpmCleanPath(nfilename);
if ((xx = Rename(ofilename, nfilename)) != 0)
if (Rename(ofilename, nfilename) != 0)
rc = 1;
else if (selinux && stat(nfilename, &st) == 0) {
security_context_t scon = NULL;
if (matchpathcon(nfilename, st.st_mode, &scon) != -1) {
(void) setfilecon(nfilename, scon);
freecon(scon);
}
}
}
for (i = 0; i < 16; i++) {
sprintf(ofilename, "%s/%s/__db.%03d", prefix, olddbpath, i);
@ -3138,6 +3148,10 @@ static int rpmdbMoveDatabase(const char * prefix,
case 0:
break;
}
if (selinux)
(void) matchpathcon_fini();
if (rc || _olddbapi == _newdbapi)
return rc;

View File

@ -246,6 +246,25 @@ extern int _tolower(int) __THROW /*@*/;
#include <malloc.h>
#endif
#if WITH_SELINUX
#include <selinux/selinux.h>
#else
typedef char * security_context_t;
#define freecon(_c)
#define setfilecon(_fn, _c) (-1)
#define lsetfilecon(_fn, _c) (-1)
#define is_selinux_enabled() (0)
#define matchpathcon_init(_fn) (-1)
#define matchpathcon_fini() (0)
#define matchpathcon(_fn, _fm, _c) (-1)
#define rpm_execcon(_v, _fn, _av, _envp) (0)
#endif
/*@-declundef -incondefs @*/ /* FIX: these are macros */
/**
*/