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 #include +#ifdef HAVE_SELINUX +#define XATTR_NAME_SELINUX "security.selinux" +#include +#include + +static struct selabel_handle *sehnd; +static unsigned int seprefixlen; +static char *mntpoint; +#endif + #include #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 ] [-s ] dir image_file [convert]\n"); + fprintf(stderr,"usage: mkyaffs2image [-f] [-c ] [-s ] dir image_file [file_contexts mountpoint] [convert]\n"); fprintf(stderr," -f fix file stat (mods, user, group) for device\n"); fprintf(stderr," -c set the chunk (NAND page) size. default: 2048\n"); fprintf(stderr," -s 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);