Added SELinux support
Mostly backported from rpm-4.8
This commit is contained in:
parent
df21cab192
commit
f92be4b40e
25
configure.in
25
configure.in
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
15
lib/cpio.h
15
lib/cpio.h
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
69
lib/fsm.c
69
lib/fsm.c
@ -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";
|
||||
|
@ -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. */
|
||||
|
@ -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 },
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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;
|
||||
|
14
macros.in
14
macros.in
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
19
system.h
19
system.h
@ -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 */
|
||||
/**
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user