1
0
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:
Peter Rajnoha
2010-12-13 10:43:56 +00:00
parent bda30a59b9
commit 7dfce0e467
13 changed files with 146 additions and 25 deletions

View File

@@ -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.

View File

@@ -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
===================================

View File

@@ -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"

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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 */

View File

@@ -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;

View File

@@ -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);
/*********************

View File

@@ -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;
}

View File

@@ -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