X-Git-Url: https://git.wh0rd.org/?p=dump.git;a=blobdiff_plain;f=restore%2Fxattr.c;h=ccc01c14c21e74177ce4b4af95cdf4f227b79991;hp=1182d8558317e91ad66f717c958bd9d990b53338;hb=15508d36add49ba67db4b0c64637dae09c2249f2;hpb=b630baf00fd14f5f8972e75bea7e8b80af92237c diff --git a/restore/xattr.c b/restore/xattr.c index 1182d85..ccc01c1 100644 --- a/restore/xattr.c +++ b/restore/xattr.c @@ -29,7 +29,7 @@ #ifndef lint static const char rcsid[] = - "$Id: xattr.c,v 1.2 2005/06/08 09:34:40 stelian Exp $"; + "$Id: xattr.c,v 1.6 2010/03/08 10:40:52 stelian Exp $"; #endif /* not lint */ #include @@ -43,6 +43,9 @@ static const char rcsid[] = #include #include #include +#ifdef TRANSSELINUX /*GAN6May06 SELinux MLS */ +# include +#endif #include "restore.h" #include "extern.h" #include "pathnames.h" @@ -195,12 +198,12 @@ struct ext2_xattr_entry { static int lsetxattr __P((const char *, const char *, void *, size_t, int)); static ssize_t lgetxattr __P((const char *, const char *, void *, size_t)); static ssize_t llistxattr __P((const char *, char *, size_t)); -static int xattr_cb_list __P((char *, char *, int, void *)); -static int xattr_cb_set __P((char *, char *, int, void *)); -static int xattr_cb_compare __P((char *, char *, int, void *)); +static int xattr_cb_list __P((char *, char *, int, int, void *)); +static int xattr_cb_set __P((char *, char *, int, int, void *)); +static int xattr_cb_compare __P((char *, char *, int, int, void *)); static int xattr_verify __P((char *)); static int xattr_count __P((char *, int *)); -static int xattr_walk __P((char *, int (*)(char *, char *, int, void *), void *)); +static int xattr_walk __P((char *, int (*)(char *, char *, int, int, void *), void *)); static int lsetxattr(const char *path, const char *name, void *value, size_t size, int flags) @@ -308,15 +311,17 @@ posix_acl_to_xattr(const struct posix_acl *acl, void *buffer, size_t size) { } ext_acl->a_version = POSIX_ACL_XATTR_VERSION; - if (Bcvt) - swabst("1i", (u_char *)ext_acl); +#if BYTE_ORDER == BIG_ENDIAN + swabst("1i", (u_char *)ext_acl); +#endif for (n=0; n < acl->a_count; n++, ext_entry++) { ext_entry->e_tag = acl->a_entries[n].e_tag; ext_entry->e_perm = acl->a_entries[n].e_perm; ext_entry->e_id = acl->a_entries[n].e_id; - if (Bcvt) - swabst("2s1i", (u_char *)ext_entry); +#if BYTE_ORDER == BIG_ENDIAN + swabst("2s1i", (u_char *)ext_entry); +#endif } return real_size; } @@ -334,8 +339,9 @@ ext3_acl_from_disk(const void *value, size_t size) fprintf(stderr, "ACL size too little\n"); return NULL; } - if (Bcvt) - swabst("1i", (u_char *)value); +#if BYTE_ORDER == BIG_ENDIAN + swabst("1i", (u_char *)value); +#endif if (((ext3_acl_header *)value)->a_version != EXT3_ACL_VERSION) { fprintf(stderr, "ACL version unknown\n"); return NULL; @@ -356,9 +362,10 @@ ext3_acl_from_disk(const void *value, size_t size) acl->a_count = count; for (n=0; n < count; n++) { - if (Bcvt) - swabst("2s1i", (u_char *)value); ext3_acl_entry *entry = (ext3_acl_entry *)value; +#if BYTE_ORDER == BIG_ENDIAN + swabst("2s", (u_char *)entry); +#endif if ((char *)value + sizeof(ext3_acl_entry_short) > end) goto fail; acl->a_entries[n].e_tag = entry->e_tag; @@ -374,6 +381,9 @@ ext3_acl_from_disk(const void *value, size_t size) case ACL_USER: case ACL_GROUP: +#if BYTE_ORDER == BIG_ENDIAN + swabst("4b1i", (u_char *)entry); +#endif value = (char *)value + sizeof(ext3_acl_entry); if ((char *)value > end) goto fail; @@ -399,8 +409,9 @@ fail: */ static int -xattr_cb_list(char *name, char *value, int valuelen, void *private) +xattr_cb_list(char *name, char *value, int valuelen, int isSELinux, void *private) { + isSELinux; value[valuelen] = '\0'; printf("EA: %s:%s\n", name, value); @@ -408,37 +419,67 @@ xattr_cb_list(char *name, char *value, int valuelen, void *private) } static int -xattr_cb_set(char *name, char *value, int valuelen, void *private) +xattr_cb_set(char *name, char *value, int valuelen, int isSELinux, void *private) { char *path = (char *)private; + int err; + + if (Nflag) + return GOOD; - if (lsetxattr(path, name, value, valuelen, 0) < 0) { - warn("lsetxattr %s failed", path); + isSELinux; +#ifdef TRANSSELINUX /*GAN6May06 SELinux MLS */ + if (isSELinux) + err = lsetfilecon(path, value); + else +#endif + err = lsetxattr(path, name, value, valuelen, 0); + + if (err) { + warn("%s: EA set %s:%s failed", path, name, value); return FAIL; } + return GOOD; } static int -xattr_cb_compare(char *name, char *value, int valuelen, void *private) +xattr_cb_compare(char *name, char *value, int valuelen, int isSELinux, void *private) { char *path = (char *)private; char valuef[XATTR_MAXSIZE]; int valuesz; - - valuesz = lgetxattr(path, name, valuef, XATTR_MAXSIZE); - if (valuesz < 0) { - warn("%s: lgetxattr failed\n", path); - return FAIL; + + isSELinux; +#ifdef TRANSSELINUX /*GAN6May06 SELinux MLS */ + if (isSELinux) + { + security_context_t con = NULL; + + if (lgetfilecon(path, &con) < 0) { + warn("%s: EA compare lgetfilecon failed\n", path); + return FAIL; + } + + valuesz = strlen(con) + 1; + valuef[0] = 0; + strncat(valuef, con, sizeof valuef); + freecon(con); } - - if (valuesz != valuelen) { - fprintf(stderr, "%s: EA %s value changed\n", path, value); - return FAIL; + else { +#endif + valuesz = lgetxattr(path, name, valuef, XATTR_MAXSIZE); + if (valuesz < 0) { + warn("%s: EA compare lgetxattr failed\n", path); + return FAIL; + } +#ifdef TRANSSELINUX /*GAN6May06 SELinux MLS */ } - - if (memcmp(value, valuef, valuelen)) { - fprintf(stderr, "%s: EA %s value changed\n", path, value); +#endif + + if (valuesz != valuelen || memcmp(value, valuef, valuelen)) { + /* GAN24May06: show name and new value for user to compare */ + fprintf(stderr, "%s: EA %s:%s value changed to %s\n", path, name, value, valuef); return FAIL; } @@ -453,8 +494,9 @@ xattr_verify(char *buffer) end = buffer + XATTR_MAXSIZE; - if (Bcvt) - swabst("4i", (u_char *)buffer); +#if BYTE_ORDER == BIG_ENDIAN + swabst("4i", (u_char *)buffer); +#endif if (HDR(buffer)->h_magic != EXT2_XATTR_MAGIC && HDR(buffer)->h_magic != EXT2_XATTR_MAGIC2) { @@ -466,8 +508,9 @@ xattr_verify(char *buffer) /* check the on-disk data structure */ entry = FIRST_ENTRY(buffer); - if (Bcvt) - swabst("2b1s3i", (u_char *)entry); +#if BYTE_ORDER == BIG_ENDIAN + swabst("2b1s3i", (u_char *)entry); +#endif while (!IS_LAST_ENTRY(entry)) { struct ext2_xattr_entry *next = EXT2_XATTR_NEXT(entry); @@ -476,8 +519,9 @@ xattr_verify(char *buffer) return FAIL; } entry = next; - if (Bcvt) - swabst("2b1s3i", (u_char *)entry); +#if BYTE_ORDER == BIG_ENDIAN + swabst("2b1s3i", (u_char *)entry); +#endif } return GOOD; } @@ -498,7 +542,7 @@ xattr_count(char *buffer, int *count) } static int -xattr_walk(char *buffer, int (*xattr_cb)(char *, char *, int, void *), void *private) +xattr_walk(char *buffer, int (*xattr_cb)(char *, char *, int, int, void *), void *private) { struct ext2_xattr_entry *entry; @@ -506,8 +550,10 @@ xattr_walk(char *buffer, int (*xattr_cb)(char *, char *, int, void *), void *pri for (entry = FIRST_ENTRY(buffer); !IS_LAST_ENTRY(entry); entry = EXT2_XATTR_NEXT(entry)) { char name[XATTR_MAXSIZE], value[XATTR_MAXSIZE]; + int size; int off; int convertacl = 0; + int convertcon = 0; switch (entry->e_name_index) { case EXT2_XATTR_INDEX_USER: @@ -529,6 +575,9 @@ xattr_walk(char *buffer, int (*xattr_cb)(char *, char *, int, void *), void *pri break; case EXT2_XATTR_INDEX_SECURITY: strcpy(name, "security."); +#ifdef TRANSSELINUX /*GAN6May06 SELinux MLS */ + convertcon = transselinuxflag; +#endif break; default: fprintf(stderr, "Unknown EA index\n"); @@ -538,24 +587,51 @@ xattr_walk(char *buffer, int (*xattr_cb)(char *, char *, int, void *), void *pri off = strlen(name); memcpy(name + off, entry->e_name, entry->e_name_len); name[off + entry->e_name_len] = '\0'; + size = entry->e_value_size; - memcpy(value, buffer + VALUE_OFFSET(buffer, entry), entry->e_value_size); + memcpy(value, buffer + VALUE_OFFSET(buffer, entry), size); if (convertacl) { struct posix_acl *acl; - int size; - acl = ext3_acl_from_disk(value, entry->e_value_size); + acl = ext3_acl_from_disk(value, size); if (!acl) return FAIL; size = posix_acl_to_xattr(acl, value, XATTR_MAXSIZE); if (size < 0) return FAIL; - entry->e_value_size = size; free(acl); } + +#ifdef TRANSSELINUX /*GAN6May06 SELinux MLS */ + if (convertcon && strcmp(name, "security.selinux")) + convertcon = 0; /*GAN24May06 only for selinux */ + + if (convertcon) + { + security_context_t con = NULL; + int err; + + if (!transselinuxarg) + err = security_canonicalize_context(value, &con); + else { + strncat(value, transselinuxarg, sizeof value); + err = security_canonicalize_context_raw(value, &con); + } + + if (err < 0) { + warn("%s: EA canonicalize failed\n", value); + return FAIL; + } + + size = strlen(con) + 1; + value[0] = 0; + strncat(value, con, sizeof value); + freecon(con); + } +#endif - if (xattr_cb(name, value, entry->e_value_size, private) != GOOD) + if (xattr_cb(name, value, size, convertcon, private) != GOOD) return FAIL; }