Set SELinux contexts on device nodes created by vold.

Extend vold to look up and set SELinux contexts on the
device nodes it creates for extra loop devices and for volumes.
Prior to this change, these device nodes simply inherited the type
of their parent directory /dev/block, i.e. block_device, and vold
therefore required create_file perms to block_device:blk_file.
With this change we can scope vold down to accessing specific
block device types.

This depends on change Id3bea28f5958086716cd3db055bea309b3b5fa5a
to allow vold to use setfscreatecon().

Change-Id: Ib9e8294abb1da94d92503947603ec12e802ff08c
Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov>
diff --git a/Loop.cpp b/Loop.cpp
index 3f0ee1e..9ee7434 100644
--- a/Loop.cpp
+++ b/Loop.cpp
@@ -35,6 +35,7 @@
 #include <sysutils/SocketClient.h>
 #include "Loop.h"
 #include "Asec.h"
+#include "sehandle.h"
 
 int Loop::dumpState(SocketClient *c) {
     int i;
@@ -132,6 +133,7 @@
     for (i = 0; i < LOOP_MAX; i++) {
         struct loop_info64 li;
         int rc;
+        char *secontext = NULL;
 
         sprintf(filename, "/dev/block/loop%d", i);
 
@@ -141,12 +143,29 @@
          */
         mode_t mode = 0660 | S_IFBLK;
         unsigned int dev = (0xff & i) | ((i << 12) & 0xfff00000) | (7 << 8);
+
+        if (sehandle) {
+            rc = selabel_lookup(sehandle, &secontext, filename, S_IFBLK);
+            if (rc == 0)
+                setfscreatecon(secontext);
+        }
+
         if (mknod(filename, mode, dev) < 0) {
             if (errno != EEXIST) {
+                int sverrno = errno;
                 SLOGE("Error creating loop device node (%s)", strerror(errno));
+                if (secontext) {
+                    freecon(secontext);
+                    setfscreatecon(NULL);
+                }
+                errno = sverrno;
                 return -1;
             }
         }
+        if (secontext) {
+            freecon(secontext);
+            setfscreatecon(NULL);
+        }
 
         if ((fd = open(filename, O_RDWR)) < 0) {
             SLOGE("Unable to open %s (%s)", filename, strerror(errno));