mirror of
git://sourceware.org/git/lvm2.git
synced 2025-12-15 08:23:51 +03:00
Add new dm_prepare_selinux_context fn to libdevmapper and use it throughout.
Detect existence of new SELinux selabel interface during configure. Use new dm_prepare_selinux_context instead of dm_set_selinux_context. We should set the SELinux context before the actual file system object creation. The new dm_prepare_selinux_context function sets this using the selabel_lookup fn in conjuction with the setfscreatecon fn. If selinux/label.h interface (that should be a part of the selinux library) is not found during configure, we fallback to the original matchpathcon function instead.
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
Version 2.02.79 -
|
||||
===================================
|
||||
Use new dm_prepare_selinux_context instead of dm_set_selinux_context.
|
||||
Avoid revalidating the label cache immediately after scanning.
|
||||
Support scanning for a single VG in independent mdas.
|
||||
Don't skip full scan when independent mdas are present even if memlock is set.
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
Version 1.02.60 -
|
||||
===================================
|
||||
Add new dm_prepare_selinux_context fn to libdevmapper and use it throughout.
|
||||
Detect existence of new SELinux selabel interface during configure.
|
||||
|
||||
Version 1.02.59 - 6th December 2010
|
||||
===================================
|
||||
|
||||
@@ -971,6 +971,7 @@ if test x$SELINUX = xyes; then
|
||||
|
||||
AC_CHECK_LIB([selinux], [is_selinux_enabled], [
|
||||
AC_CHECK_HEADERS([selinux/selinux.h],, hard_bailout)
|
||||
AC_CHECK_HEADERS([selinux/label.h])
|
||||
AC_DEFINE([HAVE_SELINUX], 1, [Define to 1 to include support for selinux.])
|
||||
SELINUX_LIBS="-lselinux $SELINUX_LIBS"
|
||||
SELINUX_PC="libselinux"
|
||||
|
||||
@@ -43,6 +43,8 @@ static int init_comms(void)
|
||||
mode_t old_mask;
|
||||
|
||||
close_comms();
|
||||
|
||||
(void) dm_prepare_selinux_context(SINGLENODE_CLVMD_SOCKNAME, S_IFSOCK);
|
||||
old_mask = umask(0077);
|
||||
|
||||
listen_fd = socket(PF_UNIX, SOCK_STREAM, 0);
|
||||
@@ -68,9 +70,11 @@ static int init_comms(void)
|
||||
}
|
||||
|
||||
umask(old_mask);
|
||||
(void) dm_prepare_selinux_context(NULL, 0);
|
||||
return 0;
|
||||
error:
|
||||
umask(old_mask);
|
||||
(void) dm_prepare_selinux_context(NULL, 0);
|
||||
close_comms();
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -414,10 +414,12 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
/* Create pidfile */
|
||||
(void) dm_prepare_selinux_context(CLVMD_PIDFILE, S_IFREG);
|
||||
if (dm_create_lockfile(CLVMD_PIDFILE) == 0) {
|
||||
DEBUGLOG("clvmd: unable to create lockfile\n");
|
||||
exit(1);
|
||||
}
|
||||
(void) dm_prepare_selinux_context(NULL, 0);
|
||||
|
||||
atexit(remove_lockfile);
|
||||
|
||||
@@ -2020,6 +2022,8 @@ static int open_local_sock()
|
||||
mode_t old_mask;
|
||||
|
||||
close_local_sock(local_socket);
|
||||
|
||||
(void) dm_prepare_selinux_context(CLVMD_SOCKNAME, S_IFSOCK);
|
||||
old_mask = umask(0077);
|
||||
|
||||
/* Open local socket */
|
||||
@@ -2037,6 +2041,7 @@ static int open_local_sock()
|
||||
memset(&sockaddr, 0, sizeof(sockaddr));
|
||||
memcpy(sockaddr.sun_path, CLVMD_SOCKNAME, sizeof(CLVMD_SOCKNAME));
|
||||
sockaddr.sun_family = AF_UNIX;
|
||||
|
||||
if (bind(local_socket, (struct sockaddr *) &sockaddr, sizeof(sockaddr))) {
|
||||
log_error("can't bind local socket: %m");
|
||||
goto error;
|
||||
@@ -2047,10 +2052,12 @@ static int open_local_sock()
|
||||
}
|
||||
|
||||
umask(old_mask);
|
||||
(void) dm_prepare_selinux_context(NULL, 0);
|
||||
return local_socket;
|
||||
error:
|
||||
close_local_sock(local_socket);
|
||||
umask(old_mask);
|
||||
(void) dm_prepare_selinux_context(NULL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -188,8 +188,10 @@ static void daemonize(void)
|
||||
|
||||
LOG_OPEN("cmirrord", LOG_PID, LOG_DAEMON);
|
||||
|
||||
(void) dm_prepare_selinux_context(CMIRRORD_PIDFILE, S_IFREG);
|
||||
if (dm_create_lockfile(CMIRRORD_PIDFILE) == 0)
|
||||
exit(EXIT_LOCKFILE);
|
||||
(void) dm_prepare_selinux_context(NULL, 0);
|
||||
|
||||
atexit(remove_lockfile);
|
||||
|
||||
|
||||
@@ -1241,14 +1241,30 @@ static void _init_fifos(struct dm_event_fifos *fifos)
|
||||
/* Open fifos used for client communication. */
|
||||
static int _open_fifos(struct dm_event_fifos *fifos)
|
||||
{
|
||||
/* Create fifos */
|
||||
if (((mkfifo(fifos->client_path, 0600) == -1) && errno != EEXIST) ||
|
||||
((mkfifo(fifos->server_path, 0600) == -1) && errno != EEXIST)) {
|
||||
syslog(LOG_ERR, "%s: Failed to create a fifo.\n", __func__);
|
||||
int orig_errno;
|
||||
|
||||
/* Create client fifo. */
|
||||
(void) dm_prepare_selinux_context(fifos->client_path, S_IFIFO);
|
||||
if ((mkfifo(fifos->client_path, 0600) == -1) && errno != EEXIST) {
|
||||
syslog(LOG_ERR, "%s: Failed to create client fifo.\n", __func__);
|
||||
orig_errno = errno;
|
||||
(void) dm_prepare_selinux_context(NULL, 0);
|
||||
stack;
|
||||
return -errno;
|
||||
return -orig_errno;
|
||||
}
|
||||
|
||||
/* Create server fifo. */
|
||||
(void) dm_prepare_selinux_context(fifos->server_path, S_IFIFO);
|
||||
if ((mkfifo(fifos->server_path, 0600) == -1) && errno != EEXIST) {
|
||||
syslog(LOG_ERR, "%s: Failed to create server fifo.\n", __func__);
|
||||
orig_errno = errno;
|
||||
(void) dm_prepare_selinux_context(NULL, 0);
|
||||
stack;
|
||||
return -orig_errno;
|
||||
}
|
||||
|
||||
(void) dm_prepare_selinux_context(NULL, 0);
|
||||
|
||||
struct stat st;
|
||||
|
||||
/* Warn about wrong permissions if applicable */
|
||||
@@ -1806,10 +1822,12 @@ int main(int argc, char *argv[])
|
||||
|
||||
openlog("dmeventd", LOG_PID, LOG_DAEMON);
|
||||
|
||||
(void) dm_prepare_selinux_context(DMEVENTD_PIDFILE, S_IFREG);
|
||||
if (dm_create_lockfile(DMEVENTD_PIDFILE) == 0)
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
atexit(remove_lockfile);
|
||||
(void) dm_prepare_selinux_context(NULL, 0);
|
||||
|
||||
/* Set the rest of the signals to cause '_exit_now' to be set */
|
||||
signal(SIGINT, &_exit_handler);
|
||||
|
||||
@@ -43,13 +43,16 @@ static int _mk_dir(const char *dev_dir, const char *vg_name)
|
||||
|
||||
log_very_verbose("Creating directory %s", vg_path);
|
||||
|
||||
(void) dm_prepare_selinux_context(vg_path, S_IFDIR);
|
||||
old_umask = umask(DM_DEV_DIR_UMASK);
|
||||
if (mkdir(vg_path, 0777)) {
|
||||
log_sys_error("mkdir", vg_path);
|
||||
umask(old_umask);
|
||||
(void) dm_prepare_selinux_context(NULL, 0);
|
||||
return 0;
|
||||
}
|
||||
umask(old_umask);
|
||||
(void) dm_prepare_selinux_context(NULL, 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -199,13 +202,14 @@ static int _mk_link(const char *dev_dir, const char *vg_name,
|
||||
"direct link creation.", lv_path);
|
||||
|
||||
log_very_verbose("Linking %s -> %s", lv_path, link_path);
|
||||
|
||||
(void) dm_prepare_selinux_context(lv_path, S_IFLNK);
|
||||
if (symlink(link_path, lv_path) < 0) {
|
||||
log_sys_error("symlink", lv_path);
|
||||
(void) dm_prepare_selinux_context(NULL, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!dm_set_selinux_context(lv_path, S_IFLNK))
|
||||
return_0;
|
||||
(void) dm_prepare_selinux_context(NULL, 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -234,10 +234,12 @@ static int _lock_file(const char *file, uint32_t flags)
|
||||
log_very_verbose("Locking %s %c%c", ll->res, state,
|
||||
nonblock ? ' ' : 'B');
|
||||
|
||||
(void) dm_prepare_selinux_context(file, S_IFREG);
|
||||
if (_prioritise_write_locks)
|
||||
r = _do_write_priority_flock(file, &ll->lf, operation, nonblock);
|
||||
else
|
||||
r = _do_flock(file, &ll->lf, operation, nonblock);
|
||||
(void) dm_prepare_selinux_context(NULL, 0);
|
||||
|
||||
if (r)
|
||||
dm_list_add(&_lock_list, &ll->list);
|
||||
@@ -325,6 +327,7 @@ int init_file_locking(struct locking_type *locking, struct cmd_context *cmd)
|
||||
locking->reset_locking = _reset_file_locking;
|
||||
locking->fin_locking = _fin_file_locking;
|
||||
locking->flags = 0;
|
||||
int r;
|
||||
|
||||
/* Get lockfile directory from config file */
|
||||
strncpy(_lock_dir, find_config_tree_str(cmd, "global/locking_dir",
|
||||
@@ -335,7 +338,11 @@ int init_file_locking(struct locking_type *locking, struct cmd_context *cmd)
|
||||
find_config_tree_bool(cmd, "global/prioritise_write_locks",
|
||||
DEFAULT_PRIORITISE_WRITE_LOCKS);
|
||||
|
||||
if (!dm_create_dir(_lock_dir))
|
||||
(void) dm_prepare_selinux_context(_lock_dir, S_IFDIR);
|
||||
r = dm_create_dir(_lock_dir);
|
||||
(void) dm_prepare_selinux_context(NULL, 0);
|
||||
|
||||
if (!r)
|
||||
return 0;
|
||||
|
||||
/* Trap a read-only file system */
|
||||
|
||||
@@ -270,27 +270,25 @@ static int _create_control(const char *control, uint32_t major, uint32_t minor)
|
||||
if (!major)
|
||||
return 0;
|
||||
|
||||
(void) dm_prepare_selinux_context(dm_dir(), S_IFDIR);
|
||||
old_umask = umask(DM_DEV_DIR_UMASK);
|
||||
ret = dm_create_dir(dm_dir());
|
||||
umask(old_umask);
|
||||
(void) dm_prepare_selinux_context(NULL, 0);
|
||||
|
||||
if (!ret)
|
||||
return 0;
|
||||
|
||||
log_verbose("Creating device %s (%u, %u)", control, major, minor);
|
||||
|
||||
(void) dm_prepare_selinux_context(control, S_IFCHR);
|
||||
if (mknod(control, S_IFCHR | S_IRUSR | S_IWUSR,
|
||||
MKDEV(major, minor)) < 0) {
|
||||
log_sys_error("mknod", control);
|
||||
(void) dm_prepare_selinux_context(NULL, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef HAVE_SELINUX
|
||||
if (!dm_set_selinux_context(control, S_IFCHR)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
(void) dm_prepare_selinux_context(NULL, 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -2132,6 +2130,7 @@ void dm_pools_check_leaks(void);
|
||||
void dm_lib_exit(void)
|
||||
{
|
||||
dm_lib_release();
|
||||
selinux_release();
|
||||
if (_dm_bitset)
|
||||
dm_bitset_destroy(_dm_bitset);
|
||||
_dm_bitset = NULL;
|
||||
|
||||
@@ -923,6 +923,17 @@ unsigned int dm_list_size(const struct dm_list *head);
|
||||
/*********
|
||||
* selinux
|
||||
*********/
|
||||
|
||||
/*
|
||||
* Obtain SELinux security context assigned for the path and set this
|
||||
* context for creating a new file system object. This security context
|
||||
* is global and it is used until reset to default policy behaviour
|
||||
* by calling 'dm_prepare_selinux_context(NULL, 0)'.
|
||||
*/
|
||||
int dm_prepare_selinux_context(const char *path, mode_t mode);
|
||||
/*
|
||||
* Set SELinux context for existing file system object.
|
||||
*/
|
||||
int dm_set_selinux_context(const char *path, mode_t mode);
|
||||
|
||||
/*********************
|
||||
|
||||
@@ -40,6 +40,9 @@
|
||||
#ifdef HAVE_SELINUX
|
||||
# include <selinux/selinux.h>
|
||||
#endif
|
||||
#ifdef HAVE_SELINUX_LABEL_H
|
||||
# include <selinux/label.h>
|
||||
#endif
|
||||
|
||||
#define DEV_DIR "/dev/"
|
||||
|
||||
@@ -59,6 +62,10 @@ static char _dm_dir[PATH_MAX] = DEV_DIR DM_DIR;
|
||||
|
||||
static int _verbose = 0;
|
||||
|
||||
#ifdef HAVE_SELINUX_LABEL_H
|
||||
static struct selabel_handle *_selabel_handle = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef UDEV_SYNC_SUPPORT
|
||||
static int _semaphore_supported = -1;
|
||||
static int _udev_running = -1;
|
||||
@@ -380,6 +387,57 @@ int dm_task_add_target(struct dm_task *dmt, uint64_t start, uint64_t size,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _selabel_lookup(const char *path, mode_t mode,
|
||||
security_context_t *scontext)
|
||||
{
|
||||
#ifdef HAVE_SELINUX_LABEL_H
|
||||
if (!_selabel_handle &&
|
||||
!(_selabel_handle = selabel_open(SELABEL_CTX_FILE, NULL, 0))) {
|
||||
log_error("selabel_open failed: %s", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (selabel_lookup(_selabel_handle, scontext, path, mode)) {
|
||||
log_error("selabel_lookup failed: %s", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
if (matchpathcon(path, mode, scontext)) {
|
||||
log_error("matchpathcon failed: %s", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
int dm_prepare_selinux_context(const char *path, mode_t mode)
|
||||
{
|
||||
#ifdef HAVE_SELINUX
|
||||
security_context_t scontext = NULL;
|
||||
|
||||
if (is_selinux_enabled() <= 0)
|
||||
return 1;
|
||||
|
||||
if (path) {
|
||||
if (!_selabel_lookup(path, mode, &scontext))
|
||||
return_0;
|
||||
|
||||
log_debug("Preparing SELinux context for %s to %s.", path, scontext);
|
||||
}
|
||||
else
|
||||
log_debug("Resetting SELinux context to default value.");
|
||||
|
||||
if (setfscreatecon(scontext) < 0) {
|
||||
log_sys_error("setfscreatecon", path);
|
||||
freecon(scontext);
|
||||
return 0;
|
||||
}
|
||||
|
||||
freecon(scontext);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
int dm_set_selinux_context(const char *path, mode_t mode)
|
||||
{
|
||||
#ifdef HAVE_SELINUX
|
||||
@@ -388,11 +446,8 @@ int dm_set_selinux_context(const char *path, mode_t mode)
|
||||
if (is_selinux_enabled() <= 0)
|
||||
return 1;
|
||||
|
||||
if (matchpathcon(path, mode, &scontext) < 0) {
|
||||
log_error("%s: matchpathcon %07o failed: %s", path, mode,
|
||||
strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
if (!_selabel_lookup(path, mode, &scontext))
|
||||
return_0;
|
||||
|
||||
log_debug("Setting SELinux context for %s to %s.", path, scontext);
|
||||
|
||||
@@ -407,6 +462,15 @@ int dm_set_selinux_context(const char *path, mode_t mode)
|
||||
return 1;
|
||||
}
|
||||
|
||||
void selinux_release(void)
|
||||
{
|
||||
#ifdef HAVE_SELINUX_LABEL_H
|
||||
if (_selabel_handle)
|
||||
selabel_close(_selabel_handle);
|
||||
_selabel_handle = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int _add_dev_node(const char *dev_name, uint32_t major, uint32_t minor,
|
||||
uid_t uid, gid_t gid, mode_t mode, int check_udev)
|
||||
{
|
||||
@@ -438,13 +502,16 @@ static int _add_dev_node(const char *dev_name, uint32_t major, uint32_t minor,
|
||||
log_warn("%s not set up by udev: Falling back to direct "
|
||||
"node creation.", path);
|
||||
|
||||
(void) dm_prepare_selinux_context(path, S_IFBLK);
|
||||
old_mask = umask(0);
|
||||
if (mknod(path, S_IFBLK | mode, dev) < 0) {
|
||||
umask(old_mask);
|
||||
log_error("Unable to make device node for '%s'", dev_name);
|
||||
umask(old_mask);
|
||||
(void) dm_prepare_selinux_context(NULL, 0);
|
||||
return 0;
|
||||
}
|
||||
umask(old_mask);
|
||||
(void) dm_prepare_selinux_context(NULL, 0);
|
||||
|
||||
if (chown(path, uid, gid) < 0) {
|
||||
log_sys_error("chown", path);
|
||||
@@ -453,9 +520,6 @@ static int _add_dev_node(const char *dev_name, uint32_t major, uint32_t minor,
|
||||
|
||||
log_debug("Created %s", path);
|
||||
|
||||
if (!dm_set_selinux_context(path, S_IFBLK))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,5 +31,6 @@ int get_dev_node_read_ahead(const char *dev_name, uint32_t *read_ahead);
|
||||
int set_dev_node_read_ahead(const char *dev_name, uint32_t read_ahead,
|
||||
uint32_t read_ahead_flags);
|
||||
void update_devs(void);
|
||||
void selinux_release(void);
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user