diff --git a/mp4-LSM/mp4.c b/mp4-LSM/mp4.c index 10e88847c319bfda832d778abbbd256140d5ca63..d9c9183529efe49c95f189822adc60480f0ff893 100755 --- a/mp4-LSM/mp4.c +++ b/mp4-LSM/mp4.c @@ -10,7 +10,7 @@ #include "mp4_given.h" typedef struct mp4_security mp4_security_t; -#define XATTR_LEN 32 +#define XATTR_LEN 64 #define PATH_BUF 512 /** * get_inode_sid - Get the inode mp4 security label id @@ -26,7 +26,7 @@ static int get_inode_sid(struct inode *inode) * Add your code here * ... */ - char *buf; + /*char *buf; struct dentry *dentry; int rc; @@ -41,17 +41,17 @@ static int get_inode_sid(struct inode *inode) if(!(inode->i_op->getxattr)){ // not impletment handler - if(printk_ratelimit()){ - pr_alert("input inode structure does not impletment getxattr\n"); - } + //if(printk_ratelimit()){ + //pr_alert("input inode structure does not impletment getxattr\n"); + //} return MP4_NO_ACCESS; } dentry = d_find_alias(inode); if(!dentry){ - if(printk_ratelimit()){ - pr_alert("cannot find dentry for inode at get_inode_sid\n"); - } + //if(printk_ratelimit()){ + //pr_alert("cannot find dentry for inode at get_inode_sid\n"); + //} return -1; } @@ -73,7 +73,68 @@ static int get_inode_sid(struct inode *inode) xattr_cred = __cred_ctx_to_sid(buf); } kfree(buf); - return xattr_cred; + return xattr_cred;*/ + char * cred_ctx; + struct dentry *de = d_find_alias(inode); + int ret, sid, len; + + if (!de) { + pr_err("%s, NULL dentry\n", __func__); + return -EFAULT; + } + + len = XATTR_LEN; + cred_ctx = kmalloc(len, GFP_NOFS); + if (!cred_ctx) { + dput(de); + pr_err("%s, could not allocate mem\n", __func__); + return -ENOMEM; + } + // Clean the momory + memset(cred_ctx, 0, len); + + if (!inode->i_op->getxattr) { + dput(de); + kfree(cred_ctx); + return 0; + } + + ret = inode->i_op->getxattr(de, XATTR_NAME_MP4, cred_ctx, len); + + if (ret == -ERANGE) { + ret = inode->i_op->getxattr(de, XATTR_NAME_MP4, NULL, 0); + if (ret < 0) { + dput(de); + pr_err("%s, query the correct size of xattr failed", __func__); + return ret; + } + + len = ret; + cred_ctx = kmalloc(len + 1, GFP_NOFS); + if (!cred_ctx) { + dput(de); + return -ENOMEM; + } + cred_ctx[len] = 0; + ret = inode->i_op->getxattr(de, XATTR_NAME_MP4, cred_ctx, len); + } + + dput(de); + + if (ret < 0) { + if (ret != -ENODATA) { + pr_err("%s, get the xattr failed\n", __func__); + kfree(cred_ctx); + return ret; + } + + } else { + sid = __cred_ctx_to_sid(cred_ctx); + ret = sid; + } + + kfree(cred_ctx); + return ret; } /** @@ -292,12 +353,9 @@ static int mp4_inode_init_security(struct inode *inode, struct inode *dir, * returns 0 is access granter, -EACCES otherwise * */ +/* static int mp4_has_permission(int ssid, int osid, int mask) { - /* - * Add your code here - * ... - */ int rc = -1; if(osid == MP4_TARGET_SID){ // object file is labeled @@ -422,7 +480,7 @@ static int mp4_has_permission(int ssid, int osid, int mask) } } return rc; -} +}*/ /** * mp4_inode_permission - Check permission for an inode being opened @@ -435,12 +493,10 @@ static int mp4_has_permission(int ssid, int osid, int mask) * returns 0 if access is granted, -EACCES otherwise * */ +/* static int mp4_inode_permission(struct inode *inode, int mask) { - /* - * Add your code here - * ... - */ + const struct mp4_security *cur_sec; struct dentry *dentry; char* buf; @@ -509,6 +565,171 @@ static int mp4_inode_permission(struct inode *inode, int mask) return -EACCES; } + return 0; +}*/ + +static int mp4_has_permission(int ssid, int osid, int mask) +{ + /* + * Add your code here + * ... + */ + + // If there are no masks about the MAY_READ/MAY_WRITE/MAY_ACCESS/MAY_EXEC + // pass the permission control to the Linux default access control + mask &= (MAY_READ|MAY_WRITE|MAY_APPEND|MAY_ACCESS|MAY_EXEC); + if (!mask) + goto PERMIT; + + switch(osid) { + // May not be accessed by target, but may be any others + // So if the ssid is target, just deny + case MP4_NO_ACCESS: + if (ssid == MP4_TARGET_SID) + goto DENY; + else + goto PERMIT; + // May only be read by anyone + case MP4_READ_OBJ: + if ((mask & (MAY_READ)) == mask) + goto PERMIT; + else + goto DENY; + // May be read/write/append by target + // and read by others + case MP4_READ_WRITE: + if (ssid == MP4_TARGET_SID) + if ((mask & (MAY_READ | MAY_WRITE | MAY_APPEND)) == mask) + goto PERMIT; + else + goto DENY; + else + if ((mask & (MAY_READ)) == mask) + goto PERMIT; + else + goto DENY; + // May be written/appended by target + // and only read by others + case MP4_WRITE_OBJ: + if (ssid == MP4_TARGET_SID) + if ((mask & (MAY_WRITE | MAY_APPEND)) == mask) + goto PERMIT; + else + goto DENY; + else + if ((mask & (MAY_READ)) == mask) + goto PERMIT; + else + goto DENY; + // May be read/executed by all + case MP4_EXEC_OBJ: + if ((mask & (MAY_READ | MAY_EXEC)) == mask) + goto PERMIT; + else + goto DENY; + // May be read/exec/access by all + case MP4_READ_DIR: + if (ssid == MP4_TARGET_SID) + if ((mask & (MAY_READ | MAY_EXEC | MAY_ACCESS)) == mask) + goto PERMIT; + else + goto DENY; + else + goto PERMIT; + // May be modified by all, so just permit + case MP4_RW_DIR: + if (ssid == MP4_TARGET_SID) + goto PERMIT; + else + goto PERMIT; + } +PERMIT: + return 0; +DENY: + return -EACCES; +} + +/** + * mp4_inode_permission - Check permission for an inode being opened + * + * @inode: the inode in question + * @mask: the access requested + * + * This is the important access check hook + * + * returns 0 if access is granted, -EACCES otherwise + * + */ +static int mp4_inode_permission(struct inode *inode, int mask) +{ + /* + * Add your code here + * ... + */ + struct dentry *de; + const struct cred *cur_cred = current_cred(); + struct mp4_security *mp4_ctx; + char *res, *buf; + int osid, ssid; + + if (!inode) + return 0; + + // Find the dentry from inode + de = d_find_alias(inode); + if (!de) + return 0; + + buf = kzalloc(255 * sizeof(char), GFP_KERNEL); + if (!buf) { + dput(de); + return 0; + } + + // Get the dentry corresponding path + res = dentry_path_raw(de, buf, 255); + if (IS_ERR(res)) { + pr_err("%s, could not find path\n", __func__); + kfree(buf); + dput(de); + return 0; + } + + // Skip the pathes which has the prefixes described in helper func + if (mp4_should_skip_path(res)) { + kfree(buf); + dput(de); + return 0; + } + + // Get the object sid + osid = get_inode_sid(inode); + if (osid < 0) { + /*pr_err("%s, could not get osid\n", __func__);*/ + osid = MP4_NO_ACCESS; + } + + kfree(buf); + dput(de); + + // Check the current task credential + if (!cur_cred) + return 0; + + // Get the sid of the current task + ssid = MP4_NO_ACCESS; + mp4_ctx = cur_cred->security; + if (mp4_ctx) + ssid = mp4_ctx->mp4_flags; + + /*pr_info("%s, ssid %d, osid %d\n", res, ssid, osid);*/ + + // Check the permissions + if (mp4_has_permission(ssid, osid, mask)) { + pr_info("%s, DENY: ssid %d, osid %d, mask 0x%x\n", res, ssid, osid, mask); + return -EACCES; + } + return 0; }