]> sourceware.org Git - lvm2.git/commitdiff
Add new dm_prepare_selinux_context fn to libdevmapper and use it throughout.
authorPeter Rajnoha <prajnoha@redhat.com>
Mon, 13 Dec 2010 10:43:56 +0000 (10:43 +0000)
committerPeter Rajnoha <prajnoha@redhat.com>
Mon, 13 Dec 2010 10:43:56 +0000 (10:43 +0000)
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.

13 files changed:
WHATS_NEW
WHATS_NEW_DM
configure.in
daemons/clvmd/clvmd-singlenode.c
daemons/clvmd/clvmd.c
daemons/cmirrord/clogd.c
daemons/dmeventd/dmeventd.c
lib/activate/fs.c
lib/locking/file_locking.c
libdm/ioctl/libdm-iface.c
libdm/libdevmapper.h
libdm/libdm-common.c
libdm/libdm-common.h

index 2d23413c577ebd7c5116576a35234991d6a3079a..859668fb7e5ec2fcdeb2d971821dfbedeb461596 100644 (file)
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -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.
index 5e83a49969e26531973de57fc9670d87da44d74d..8d4b02610c36c072116ae806dfc647f43f2cb822 100644 (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
 ===================================
index 97f538eefa48f8b3eac79c6a1a224327b7e59163..6cb5e8dbeedd0f6980b1270553ca62ea4b37bcfd 100644 (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"
index 75a23d61c8c03052f509c27a31a349053848633a..335cb98f53fdd8b54360ee6b54fe15293ee2702a 100644 (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;
 }
index 40d7feb844daa2787e024d04d0c63f7c6cf4fa43..73fbbaa9b8c33350a95afa9660fe737eb9525a7b 100644 (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;
 }
 
index 7e354d92beebe518b9e1fc1ecfedaf6addce9bc2..8d9a7b9af2b6ab1fbd28076ee7b0b67c01e5cc98 100644 (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);
 
index 3f015bdc5bbd336ffc97413049fcc78f17409ca7..392d99eea5021b1ae03c61037c4f4153583c7077 100644 (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);
index b78da112ced1f3f7eabbcee3b00fa9446fdf8109..1523115ba8f1b924647db71c9dc21f0a8680f45d 100644 (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;
 }
index ed1ccd5706b4e2bc54c31ffcf008f696bf56b376..9137a30a51306fa93bf079249d073c93d50abeeb 100644 (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 */
index b18249a9d109cdc57b05042b49c318bc5709ac97..4a8dfc64fb41a4a415b810b6730438bacb56825a 100644 (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;
index e2f2673300c1c26fe776661aa850a9635be08add..3083f9a194441361ed668b8ef4915a4da43b6837 100644 (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);
 
 /*********************
index 2dfa28f6a8df44845f890a241cde3d756119299f..cca29a7f907c635d5c69a3076eebb838dbebe497 100644 (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,20 +387,68 @@ int dm_task_add_target(struct dm_task *dmt, uint64_t start, uint64_t size,
        return 1;
 }
 
-int dm_set_selinux_context(const char *path, mode_t mode)
+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;
+       security_context_t scontext = NULL;
 
        if (is_selinux_enabled() <= 0)
                return 1;
 
-       if (matchpathcon(path, mode, &scontext) < 0) {
-               log_error("%s: matchpathcon %07o failed: %s", path, mode,
-                         strerror(errno));
+       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
+       security_context_t scontext;
+
+       if (is_selinux_enabled() <= 0)
+               return 1;
+
+       if (!_selabel_lookup(path, mode, &scontext))
+               return_0;
+
        log_debug("Setting SELinux context for %s to %s.", path, scontext);
 
        if ((lsetfilecon(path, scontext) < 0) && (errno != ENOTSUP)) {
@@ -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;
 }
 
index fcb334f847282253aa6a8636cea035e92f433ee2..3267cfc496dc80ccb83a8ee1a30bf1e58a85da37 100644 (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
This page took 0.065673 seconds and 5 git commands to generate.