summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimo Teräs <timo.teras@iki.fi>2015-04-08 10:25:44 +0300
committerTimo Teräs <timo.teras@iki.fi>2015-04-08 10:27:49 +0300
commit83ab02230115eab725bf92f111f4a3f2a41db5b1 (patch)
tree546b0f9a8ceb1aefc3b36ef000f3354784c13dbd
parent944eae4b27d039608dd72b1d7b3ed015c20bdcc0 (diff)
downloadapk-tools-83ab02230115eab725bf92f111f4a3f2a41db5b1.tar.gz
apk-tools-83ab02230115eab725bf92f111f4a3f2a41db5b1.tar.bz2
apk-tools-83ab02230115eab725bf92f111f4a3f2a41db5b1.tar.xz
apk-tools-83ab02230115eab725bf92f111f4a3f2a41db5b1.zip
audit xattrs
ref #3027
-rw-r--r--src/apk_io.h2
-rw-r--r--src/audit.c28
-rw-r--r--src/io.c98
3 files changed, 90 insertions, 38 deletions
diff --git a/src/apk_io.h b/src/apk_io.h
index ee81851..6e2e37c 100644
--- a/src/apk_io.h
+++ b/src/apk_io.h
@@ -149,6 +149,8 @@ apk_blob_t apk_blob_from_file(int atfd, const char *file);
int apk_blob_to_file(int atfd, const char *file, apk_blob_t b, unsigned int flags);
#define APK_FI_NOFOLLOW 0x80000000
+#define APK_FI_XATTR_CSUM(x) (((x) & 0xff) << 8)
+#define APK_FI_CSUM(x) (((x) & 0xff))
int apk_fileinfo_get(int atfd, const char *filename, unsigned int flags,
struct apk_file_info *fi);
void apk_fileinfo_hash_xattr(struct apk_file_info *fi);
diff --git a/src/audit.c b/src/audit.c
index 3bc525b..cb295b8 100644
--- a/src/audit.c
+++ b/src/audit.c
@@ -93,30 +93,36 @@ static int audit_file(struct audit_ctx *actx,
int dirfd, const char *name)
{
struct apk_file_info fi;
+ int rv = 0;
if (dbf == NULL)
return 'A';
dbf->audited = 1;
- if (apk_fileinfo_get(dirfd, name, APK_FI_NOFOLLOW | dbf->csum.type, &fi) != 0)
+ if (apk_fileinfo_get(dirfd, name,
+ APK_FI_NOFOLLOW |
+ APK_FI_XATTR_CSUM(dbf->acl->xattr_csum.type ?: APK_CHECKSUM_DEFAULT) |
+ APK_FI_CSUM(dbf->csum.type),
+ &fi) != 0)
return -EPERM;
if (dbf->csum.type != APK_CHECKSUM_NONE &&
apk_checksum_compare(&fi.csum, &dbf->csum) != 0)
- return 'U';
-
- if (S_ISLNK(fi.mode) && dbf->csum.type == APK_CHECKSUM_NONE)
- return 'U';
-
- if (actx->check_permissions) {
+ rv = 'U';
+ else if (apk_checksum_compare(&fi.xattr_csum, &dbf->acl->xattr_csum) != 0)
+ rv = 'X';
+ else if (S_ISLNK(fi.mode) && dbf->csum.type == APK_CHECKSUM_NONE)
+ rv = 'U';
+ else if (actx->check_permissions) {
if ((fi.mode & 07777) != (dbf->acl->mode & 07777))
- return 'M';
- if (fi.uid != dbf->acl->uid || fi.gid != dbf->acl->gid)
- return 'M';
+ rv = 'M';
+ else if (fi.uid != dbf->acl->uid || fi.gid != dbf->acl->gid)
+ rv = 'M';
}
+ apk_fileinfo_free(&fi);
- return 0;
+ return rv;
}
static int audit_directory(struct audit_ctx *actx,
diff --git a/src/io.c b/src/io.c
index 8a23bb4..5debb5f 100644
--- a/src/io.c
+++ b/src/io.c
@@ -19,6 +19,7 @@
#include <sys/mman.h>
#include <sys/wait.h>
#include <sys/stat.h>
+#include <sys/xattr.h>
#include <pwd.h>
#include <grp.h>
@@ -543,26 +544,30 @@ static void hash_len_data(EVP_MD_CTX *ctx, uint32_t len, const void *ptr)
EVP_DigestUpdate(ctx, ptr, len);
}
-void apk_fileinfo_hash_xattr(struct apk_file_info *fi)
+void apk_fileinfo_hash_xattr_array(struct apk_xattr_array *xattrs, const EVP_MD *md, struct apk_checksum *csum)
{
struct apk_xattr *xattr;
- const EVP_MD *md = apk_checksum_default();
EVP_MD_CTX mdctx;
- if (!fi->xattrs || fi->xattrs->num == 0) {
- fi->xattr_csum.type = APK_CHECKSUM_NONE;
+ if (!xattrs || xattrs->num == 0) {
+ csum->type = APK_CHECKSUM_NONE;
return;
}
- qsort(fi->xattrs->item, fi->xattrs->num, sizeof(fi->xattrs->item[0]), cmp_xattr);
+ qsort(xattrs->item, xattrs->num, sizeof(xattrs->item[0]), cmp_xattr);
EVP_DigestInit(&mdctx, md);
- foreach_array_item(xattr, fi->xattrs) {
+ foreach_array_item(xattr, xattrs) {
hash_len_data(&mdctx, strlen(xattr->name), xattr->name);
hash_len_data(&mdctx, xattr->value.len, xattr->value.ptr);
}
- fi->xattr_csum.type = EVP_MD_CTX_size(&mdctx);
- EVP_DigestFinal(&mdctx, fi->xattr_csum.data, NULL);
+ csum->type = EVP_MD_CTX_size(&mdctx);
+ EVP_DigestFinal(&mdctx, csum->data, NULL);
+}
+
+void apk_fileinfo_hash_xattr(struct apk_file_info *fi)
+{
+ apk_fileinfo_hash_xattr_array(fi->xattrs, apk_checksum_default(), &fi->xattr_csum);
}
int apk_fileinfo_get(int atfd, const char *filename, unsigned int flags,
@@ -570,7 +575,9 @@ int apk_fileinfo_get(int atfd, const char *filename, unsigned int flags,
{
struct stat64 st;
struct apk_bstream *bs;
- int checksum = flags & 0xffff, atflags = 0;
+ unsigned int checksum = flags & 0xff;
+ unsigned int xattr_checksum = (flags >> 8) & 0xff;
+ int atflags = 0;
if (flags & APK_FI_NOFOLLOW)
atflags |= AT_SYMLINK_NOFOLLOW;
@@ -587,9 +594,47 @@ int apk_fileinfo_get(int atfd, const char *filename, unsigned int flags,
.device = st.st_dev,
};
- if (checksum == APK_CHECKSUM_NONE || S_ISDIR(st.st_mode))
+ if (xattr_checksum != APK_CHECKSUM_NONE) {
+ ssize_t len, vlen;
+ int fd, i, r;
+ char val[1024], buf[1024];
+
+ r = 0;
+ fd = openat(atfd, filename, O_RDONLY);
+ if (fd >= 0) {
+ len = flistxattr(fd, buf, sizeof(buf));
+ if (len > 0) {
+ struct apk_xattr_array *xattrs = NULL;
+ apk_xattr_array_init(&xattrs);
+ for (i = 0; i < len; i += strlen(&buf[i]) + 1) {
+ vlen = fgetxattr(fd, &buf[i], val, sizeof(val));
+ if (vlen < 0) {
+ r = errno;
+ if (r == ENODATA) continue;
+ break;
+ }
+ *apk_xattr_array_add(&xattrs) = (struct apk_xattr) {
+ .name = &buf[i],
+ .value = *apk_blob_atomize_dup(APK_BLOB_PTR_LEN(val, vlen)),
+ };
+ }
+ apk_fileinfo_hash_xattr_array(xattrs, apk_checksum_evp(xattr_checksum), &fi->xattr_csum);
+ apk_xattr_array_free(&xattrs);
+ } else r = errno;
+ close(fd);
+ } else r = errno;
+
+ if (r && r != ENOTSUP) return -r;
+
+ }
+
+ if (checksum == APK_CHECKSUM_NONE)
+ return 0;
+
+ if (S_ISDIR(st.st_mode))
return 0;
+ /* Checksum file content */
if ((flags & APK_FI_NOFOLLOW) && S_ISLNK(st.st_mode)) {
char *target = alloca(st.st_size);
if (target == NULL)
@@ -600,23 +645,22 @@ int apk_fileinfo_get(int atfd, const char *filename, unsigned int flags,
EVP_Digest(target, st.st_size, fi->csum.data, NULL,
apk_checksum_evp(checksum), NULL);
fi->csum.type = checksum;
- return 0;
- }
-
- bs = apk_bstream_from_file(atfd, filename);
- if (!IS_ERR_OR_NULL(bs)) {
- EVP_MD_CTX mdctx;
- apk_blob_t blob;
-
- EVP_DigestInit(&mdctx, apk_checksum_evp(checksum));
- if (bs->flags & APK_BSTREAM_SINGLE_READ)
- EVP_MD_CTX_set_flags(&mdctx, EVP_MD_CTX_FLAG_ONESHOT);
- while (!APK_BLOB_IS_NULL(blob = bs->read(bs, APK_BLOB_NULL)))
- EVP_DigestUpdate(&mdctx, (void*) blob.ptr, blob.len);
- fi->csum.type = EVP_MD_CTX_size(&mdctx);
- EVP_DigestFinal(&mdctx, fi->csum.data, NULL);
-
- bs->close(bs, NULL);
+ } else {
+ bs = apk_bstream_from_file(atfd, filename);
+ if (!IS_ERR_OR_NULL(bs)) {
+ EVP_MD_CTX mdctx;
+ apk_blob_t blob;
+
+ EVP_DigestInit(&mdctx, apk_checksum_evp(checksum));
+ if (bs->flags & APK_BSTREAM_SINGLE_READ)
+ EVP_MD_CTX_set_flags(&mdctx, EVP_MD_CTX_FLAG_ONESHOT);
+ while (!APK_BLOB_IS_NULL(blob = bs->read(bs, APK_BLOB_NULL)))
+ EVP_DigestUpdate(&mdctx, (void*) blob.ptr, blob.len);
+ fi->csum.type = EVP_MD_CTX_size(&mdctx);
+ EVP_DigestFinal(&mdctx, fi->csum.data, NULL);
+
+ bs->close(bs, NULL);
+ }
}
return 0;