libsmack: lazy initialization for SmackFS mount point
authorJarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Tue, 28 Jan 2014 07:39:03 +0000 (09:39 +0200)
committerJarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Tue, 28 Jan 2014 10:29:00 +0000 (12:29 +0200)
Mount SmackFS only when it is first needed. This enables init
daemons to directly use libsmack.

Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
libsmack/init.c
libsmack/libsmack.c

index 1d14086..51a63cc 100644 (file)
@@ -31,6 +31,7 @@
 #include <sys/vfs.h>
 #include <stdint.h>
 #include <limits.h>
+#include <pthread.h>
 
 #define SMACK_MAGIC    0x43415d53 /* "SMAC" */
 #define SMACKFS                "smackfs"
 char *smackfs_mnt = NULL;
 int smackfs_mnt_dirfd = -1;
 
+static pthread_mutex_t smackfs_mnt_lock = PTHREAD_MUTEX_INITIALIZER;
+
+static int verify_smackfs_mnt(const char *mnt);
+static int smackfs_exists(void);
+
+int init_smackfs_mnt(void)
+{
+       char *buf = NULL;
+       char *startp;
+       char *endp;
+       FILE *fp = NULL;
+       size_t len;
+       ssize_t num;
+       int ret = 0;
+
+       if (smackfs_mnt ||
+           verify_smackfs_mnt(SMACKFSMNT) == 0 ||
+           verify_smackfs_mnt(OLDSMACKFSMNT) == 0)
+               return 0;
+
+       if (!smackfs_exists())
+               return -1;
+
+       fp = fopen("/proc/mounts", "r");
+       if (!fp)
+               return -1;
+
+       __fsetlocking(fp, FSETLOCKING_BYCALLER);
+       while ((num = getline(&buf, &len, fp)) != -1) {
+               startp = strchr(buf, ' ');
+               if (!startp) {
+                       ret = -1;
+                       break;
+               }
+               startp++;
+
+               endp = strchr(startp, ' ');
+               if (!endp) {
+                       ret = -1;
+                       break;
+               }
+
+               if (!strncmp(endp + 1, SMACKFS" ", strlen(SMACKFS) + 1)) {
+                       *endp = '\0';
+                       ret = verify_smackfs_mnt(startp);
+                       break;
+               }
+       }
+
+       free(buf);
+       fclose(fp);
+       return ret;
+}
+
 static int verify_smackfs_mnt(const char *mnt)
 {
        struct statfs sfbuf;
@@ -55,13 +110,20 @@ static int verify_smackfs_mnt(const char *mnt)
        } while (rc < 0 && errno == EINTR);
 
        if (rc == 0) {
-               if ((uint32_t)sfbuf.f_type == (uint32_t)SMACK_MAGIC) {
+               if ((uint32_t) sfbuf.f_type == (uint32_t) SMACK_MAGIC) {
                        struct statvfs vfsbuf;
                        rc = statvfs(mnt, &vfsbuf);
                        if (rc == 0) {
                                if (!(vfsbuf.f_flag & ST_RDONLY)) {
-                                       smackfs_mnt = strdup(mnt);
-                                       smackfs_mnt_dirfd = fd;
+                                       pthread_mutex_lock(&smackfs_mnt_lock);
+                                       if (smackfs_mnt_dirfd == -1) {
+                                               smackfs_mnt = strdup(mnt);
+                                               smackfs_mnt_dirfd = fd;
+                                       } else {
+                                               /* Some other thread won the race. */
+                                               close(fd);
+                                       }
+                                       pthread_mutex_unlock(&smackfs_mnt_lock);
                                        return 0;
                                }
                        }
@@ -103,63 +165,6 @@ static int smackfs_exists(void)
        return exists;
 }
 
-static void init_smackmnt(void)
-{
-       char *buf=NULL, *p;
-       FILE *fp=NULL;
-       size_t len;
-       ssize_t num;
-
-       if (smackfs_mnt)
-               return;
-
-       if (verify_smackfs_mnt(SMACKFSMNT) == 0) 
-               return;
-
-       if (verify_smackfs_mnt(OLDSMACKFSMNT) == 0) 
-               return;
-
-       if (!smackfs_exists())
-               goto out;
-
-       fp = fopen("/proc/mounts", "r");
-       if (!fp)
-               goto out;
-
-       __fsetlocking(fp, FSETLOCKING_BYCALLER);
-       while ((num = getline(&buf, &len, fp)) != -1) {
-               char *tmp;
-               p = strchr(buf, ' ');
-               if (!p)
-                       goto out;
-               p++;
-
-               tmp = strchr(p, ' ');
-               if (!tmp)
-                       goto out;
-
-               if (!strncmp(tmp + 1, SMACKFS" ", strlen(SMACKFS)+1)) {
-                       *tmp = '\0';
-                       break;
-               }
-       }
-
-       if (num > 0)
-               verify_smackfs_mnt(p);
-
-out:
-       free(buf);
-       if (fp)
-               fclose(fp);
-       return;
-}
-
-static void init_lib(void) __attribute__ ((constructor));
-static void init_lib(void)
-{
-       init_smackmnt();
-}
-
 static void fini_lib(void) __attribute__ ((destructor));
 static void fini_lib(void)
 {
index bc84fc4..53689de 100644 (file)
@@ -64,6 +64,8 @@
 extern char *smackfs_mnt;
 extern int smackfs_mnt_dirfd;
 
+extern int init_smackfs_mnt(void);
+
 struct label_dict {
        char **labels;
        int nof_labels;
@@ -287,7 +289,7 @@ int smack_have_access(const char *subject, const char *object,
        ssize_t slen;
        ssize_t olen;
 
-       if (smackfs_mnt_dirfd < 0)
+       if (init_smackfs_mnt())
                return -1;
 
        slen = get_label(NULL, subject);
@@ -373,7 +375,7 @@ int smack_cipso_apply(struct smack_cipso *cipso)
        int offset;
        int use_long;
 
-       if (smackfs_mnt_dirfd < 0)
+       if (init_smackfs_mnt())
                return -1;
 
        fd = open_smackfs_file("cipso2", "cipso", &use_long);
@@ -495,6 +497,7 @@ err_out:
 
 const char *smack_smackfs_path(void)
 {
+       init_smackfs_mnt();
        return smackfs_mnt;
 }
 
@@ -603,7 +606,7 @@ int smack_revoke_subject(const char *subject)
        int fd;
        int len;
 
-       if (smackfs_mnt_dirfd < 0)
+       if (init_smackfs_mnt())
                return -1;
 
        len = get_label(NULL, subject);
@@ -649,7 +652,7 @@ static int accesses_apply(struct smack_accesses *handle, int clear)
        int change_fd;
        int use_long = 1;
 
-       if (smackfs_mnt_dirfd < 0)
+       if (init_smackfs_mnt())
                return -1;
 
        load_fd = open_smackfs_file("load2", "load", &use_long);