summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Smalley <sds@tycho.nsa.gov>2012-01-13 08:23:06 -0500
committerStephen Smalley <sds@tycho.nsa.gov>2012-04-02 11:19:38 -0400
commit84f79e8e767a95ea761f430a12adb13ce687ae7e (patch)
tree6b2b972484aff54a4f12a6339d3604accba43326
parent6232e2d5ab34a40d710e4b05ab0ec6e3727804e7 (diff)
downloadyaffs2-84f79e8e767a95ea761f430a12adb13ce687ae7e.tar.gz
Extend mkyaffs2image to support setting SELinux security contexts in yaffs2 images.
Modern yaffs2 includes support for extended attributes, and thus can support SELinux security contexts. Extend mkyaffs2image with support for looking up the right security context from the file_contexts configuration and setting it in the generated image. This is similar to the existing support for looking up the UID/GID/mode via android_filesystem_config.h and setting it, but via configuration rather than defined in a header. Change-Id: Ic86358987f39bddbb83ee928bbbc8cb213efb752
-rw-r--r--Android.mk6
-rw-r--r--yaffs2/utils/mkyaffs2image.c123
2 files changed, 114 insertions, 15 deletions
diff --git a/Android.mk b/Android.mk
index e31b6ae..e899a77 100644
--- a/Android.mk
+++ b/Android.mk
@@ -17,6 +17,12 @@ LOCAL_C_INCLUDES += $(LOCAL_PATH)/yaffs2
LOCAL_MODULE := mkyaffs2image
+ifeq ($(HAVE_SELINUX), true)
+LOCAL_C_INCLUDES += external/libselinux/include
+LOCAL_STATIC_LIBRARIES += libselinux
+LOCAL_CFLAGS += -DHAVE_SELINUX
+endif # HAVE_SELINUX
+
include $(BUILD_HOST_EXECUTABLE)
$(call dist-for-goals, dist_files, $(LOCAL_BUILT_MODULE))
diff --git a/yaffs2/utils/mkyaffs2image.c b/yaffs2/utils/mkyaffs2image.c
index 7b989f6..2b152e6 100644
--- a/yaffs2/utils/mkyaffs2image.c
+++ b/yaffs2/utils/mkyaffs2image.c
@@ -32,6 +32,16 @@
#include <string.h>
#include <unistd.h>
+#ifdef HAVE_SELINUX
+#define XATTR_NAME_SELINUX "security.selinux"
+#include <selinux/selinux.h>
+#include <selinux/label.h>
+
+static struct selabel_handle *sehnd;
+static unsigned int seprefixlen;
+static char *mntpoint;
+#endif
+
#include <private/android_filesystem_config.h>
#include "yaffs_ecc.h"
@@ -247,12 +257,23 @@ static int write_chunk(__u8 *data, __u32 objId, __u32 chunkId, __u32 nBytes)
}
-static int write_object_header(int objId, yaffs_ObjectType t, struct stat *s, int parent, const char *name, int equivalentObj, const char * alias)
+static int write_object_header(int objId, yaffs_ObjectType t, struct stat *s, int parent, const char *name, int equivalentObj, const char * alias, const char *secontext)
{
__u8 bytes[chunkSize];
yaffs_ObjectHeader *oh = (yaffs_ObjectHeader *)bytes;
+#ifdef HAVE_SELINUX
+ char *xb = (char *)bytes + sizeof(*oh);
+ int xnamelen = strlen(XATTR_NAME_SELINUX) + 1;
+ int xvalsize = 0;
+ int xreclen = 0;
+
+ if (secontext) {
+ xvalsize = strlen(secontext) + 1;
+ xreclen = sizeof(int) + xnamelen + xvalsize;
+ }
+#endif
memset(bytes,0xff,sizeof(bytes));
@@ -261,7 +282,16 @@ static int write_object_header(int objId, yaffs_ObjectType t, struct stat *s, in
oh->parentObjectId = parent;
strncpy(oh->name,name,YAFFS_MAX_NAME_LENGTH);
-
+
+#ifdef HAVE_SELINUX
+ if (xreclen) {
+ memcpy(xb, &xreclen, sizeof(int));
+ xb += sizeof(int);
+ strcpy(xb, XATTR_NAME_SELINUX);
+ xb += xnamelen;
+ memcpy(xb, secontext, xvalsize);
+ }
+#endif
if(t != YAFFS_OBJECT_TYPE_HARDLINK)
{
@@ -310,6 +340,7 @@ static int process_directory(int parent, const char *path, int fixstats)
DIR *dir;
struct dirent *entry;
+ char *secontext = NULL;
nDirectories++;
@@ -325,6 +356,10 @@ static int process_directory(int parent, const char *path, int fixstats)
strcmp(entry->d_name,".."))
{
char full_name[500];
+#ifdef HAVE_SELINUX
+ char *suffix, dest_name[500];
+ int ret;
+#endif
struct stat stats;
int equivalentObj;
int newObj;
@@ -332,7 +367,30 @@ static int process_directory(int parent, const char *path, int fixstats)
sprintf(full_name,"%s/%s",path,entry->d_name);
lstat(full_name,&stats);
-
+
+#ifdef HAVE_SELINUX
+ if (sehnd) {
+ suffix = full_name + seprefixlen;
+ ret = snprintf(dest_name,
+ sizeof dest_name,
+ "%s%s", mntpoint,
+ suffix);
+ if (ret < 0 ||
+ (size_t) ret >= sizeof dest_name) {
+ fprintf(stderr,
+ "snprintf failed on %s%s\n",
+ mntpoint, suffix);
+ exit(1);
+ }
+ if (selabel_lookup(sehnd, &secontext,
+ dest_name,
+ stats.st_mode) < 0) {
+ perror("selabel_lookup");
+ exit(1);
+ }
+ }
+#endif
+
if(S_ISLNK(stats.st_mode) ||
S_ISREG(stats.st_mode) ||
S_ISDIR(stats.st_mode) ||
@@ -356,7 +414,7 @@ static int process_directory(int parent, const char *path, int fixstats)
{
/* we need to make a hard link */
//printf("hard link to object %d\n",equivalentObj);
- error = write_object_header(newObj, YAFFS_OBJECT_TYPE_HARDLINK, &stats, parent, entry->d_name, equivalentObj, NULL);
+ error = write_object_header(newObj, YAFFS_OBJECT_TYPE_HARDLINK, &stats, parent, entry->d_name, equivalentObj, NULL, secontext);
}
else
{
@@ -373,13 +431,13 @@ static int process_directory(int parent, const char *path, int fixstats)
readlink(full_name,symname,sizeof(symname) -1);
//printf("symlink to \"%s\"\n",symname);
- error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SYMLINK, &stats, parent, entry->d_name, -1, symname);
+ error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SYMLINK, &stats, parent, entry->d_name, -1, symname, secontext);
}
else if(S_ISREG(stats.st_mode))
{
//printf("file, ");
- error = write_object_header(newObj, YAFFS_OBJECT_TYPE_FILE, &stats, parent, entry->d_name, -1, NULL);
+ error = write_object_header(newObj, YAFFS_OBJECT_TYPE_FILE, &stats, parent, entry->d_name, -1, NULL, secontext);
if(error >= 0)
{
@@ -415,27 +473,27 @@ static int process_directory(int parent, const char *path, int fixstats)
else if(S_ISSOCK(stats.st_mode))
{
//printf("socket\n");
- error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL);
+ error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL, secontext);
}
else if(S_ISFIFO(stats.st_mode))
{
//printf("fifo\n");
- error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL);
+ error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL, secontext);
}
else if(S_ISCHR(stats.st_mode))
{
//printf("character device\n");
- error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL);
+ error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL, secontext);
}
else if(S_ISBLK(stats.st_mode))
{
//printf("block device\n");
- error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL);
+ error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL, secontext);
}
else if(S_ISDIR(stats.st_mode))
{
//printf("directory\n");
- error = write_object_header(newObj, YAFFS_OBJECT_TYPE_DIRECTORY, &stats, parent, entry->d_name, -1, NULL);
+ error = write_object_header(newObj, YAFFS_OBJECT_TYPE_DIRECTORY, &stats, parent, entry->d_name, -1, NULL, secontext);
// NCB modified 10/9/2001 process_directory(1,full_name);
process_directory(newObj,full_name,fixstats);
}
@@ -447,7 +505,6 @@ static int process_directory(int parent, const char *path, int fixstats)
}
}
}
-
closedir(dir);
}
@@ -458,12 +515,14 @@ static int process_directory(int parent, const char *path, int fixstats)
static void usage(void)
{
fprintf(stderr,"mkyaffs2image: image building tool for YAFFS2 built "__DATE__"\n");
- fprintf(stderr,"usage: mkyaffs2image [-f] [-c <size>] [-s <size>] dir image_file [convert]\n");
+ fprintf(stderr,"usage: mkyaffs2image [-f] [-c <size>] [-s <size>] dir image_file [file_contexts mountpoint] [convert]\n");
fprintf(stderr," -f fix file stat (mods, user, group) for device\n");
fprintf(stderr," -c <size> set the chunk (NAND page) size. default: 2048\n");
fprintf(stderr," -s <size> set the spare (NAND OOB) size. default: 64\n");
fprintf(stderr," dir the directory tree to be converted\n");
fprintf(stderr," image_file the output file to hold the image\n");
+ fprintf(stderr," file_contexts the file contexts configuration used to assign SELinux file context attributes\n");
+ fprintf(stderr," mountpoint the directory where this image be mounted on the device\n");
fprintf(stderr," 'convert' produce a big-endian image from a little-endian machine\n");
}
@@ -474,6 +533,7 @@ int main(int argc, char *argv[])
int opt;
char *image;
char *dir;
+ char *secontext = NULL;
while ((opt = getopt(argc, argv, "fc:s:")) != -1) {
switch (opt) {
@@ -497,20 +557,44 @@ int main(int argc, char *argv[])
exit(1);
}
- if ((argc - optind < 2) || (argc - optind > 3)) {
+ if ((argc - optind < 2) || (argc - optind > 4)) {
usage();
exit(1);
}
dir = argv[optind];
+#ifdef HAVE_SELINUX
+ seprefixlen = strlen(dir);
+#endif
image = argv[optind + 1];
if (optind + 2 < argc) {
if (!strncmp(argv[optind + 2], "convert", strlen("convert")))
convert_endian = 1;
else {
+#ifdef HAVE_SELINUX
+ struct selinux_opt seopts[] = {
+ { SELABEL_OPT_PATH, argv[optind + 2] }
+ };
+ sehnd = selabel_open(SELABEL_CTX_FILE, seopts, 1);
+ if (!sehnd) {
+ perror(argv[optind + 2]);
+ usage();
+ exit(1);
+ }
+ if (optind + 3 >= argc) {
+ usage();
+ exit(1);
+ }
+ mntpoint = argv[optind + 3];
+ if (optind + 4 < argc) {
+ if (!strncmp(argv[optind + 4], "convert", strlen("convert")))
+ convert_endian = 1;
+ }
+#else
usage();
exit(1);
+#endif
}
}
@@ -550,7 +634,16 @@ int main(int argc, char *argv[])
}
//printf("Processing directory %s into image file %s\n",dir,image);
- error = write_object_header(1, YAFFS_OBJECT_TYPE_DIRECTORY, &stats, 1,"", -1, NULL);
+#ifdef HAVE_SELINUX
+ if (sehnd) {
+ if (selabel_lookup(sehnd, &secontext, mntpoint, stats.st_mode) < 0) {
+ perror("selabel_lookup");
+ exit(1);
+ }
+ }
+#endif
+
+ error = write_object_header(1, YAFFS_OBJECT_TYPE_DIRECTORY, &stats, 1,"", -1, NULL, secontext);
if(error)
error = process_directory(YAFFS_OBJECTID_ROOT,dir,fixstats);