From a927ceaef2c27b8a076f1ed764ab0bd94ddaa7e5 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 20 Mar 2009 14:39:25 +1100 Subject: [PATCH] remove more swhitches between root and the user. add subroutines to do common operations such as evaluating the permission and creating the substring to point to the parent directory --- migrate/remote-cache.c | 252 +++++++++++++++-------------------------- 1 file changed, 91 insertions(+), 161 deletions(-) diff --git a/migrate/remote-cache.c b/migrate/remote-cache.c index fef2ecf..98ef48f 100644 --- a/migrate/remote-cache.c +++ b/migrate/remote-cache.c @@ -320,7 +320,32 @@ finished: } +int verify_permission(uid_t uid, gid_t gid, char *path, int required) +{ + int ret; + int perms; + struct stat st; + struct group_list gl; + /* read parent attributes from remote site */ + ret = get_group_list(uid, &gl); + if (ret != 0) { + DEBUG(DEBUG_ERR,(__location__ " Failed to read group list\n")); + return -EACCES; + } + bzero(&st, sizeof(st)); + ret = lstat(path, &st); + if (ret == -1) { + DEBUG(DEBUG_ERR, (__location__ " Failed to lstat(%s) %s\n", path, strerror(errno))); + return -EIO; + } + perms = check_permissions(&st, uid, gid, &gl); + if (!(perms & required)) { + return -EACCES; + } + + return 0; +} static void unlink_object(const char *path) { @@ -480,6 +505,36 @@ struct cached_dir_entry { struct stat st; }; +char *get_parent_path(const char *path) +{ + char *sptr; + char *ppath = NULL; + + ppath = strdup(path); + if (ppath == NULL) { + DEBUG(DEBUG_ERR,(__location__ " failed to strdup ppath\n")); + goto finished; + } + + sptr = rindex(ppath, '/'); + if (sptr == NULL) { + free(ppath); + ppath = NULL; + goto finished; + } + *sptr = 0; + + if (ppath[0] == 0) { + free(ppath); + ppath = NULL; + goto finished; + } + +finished: + return ppath; +} + + #define CACHE_DIR_NAME ". DIRCACHE" int open_dir_cache_ro(const char *path, struct stat *old_st) @@ -519,31 +574,16 @@ finished: } - - int open_parent_cache_ro(const char *path) { - char *ppath = NULL; char *parent_path = NULL; - char *sptr; + char *ppath = NULL; struct stat parent_st; int cache_fd = -1; int ret; - ppath = strdup(path); + ppath = get_parent_path(path); if (ppath == NULL) { - DEBUG(DEBUG_ERR,(__location__ " failed to strdup ppath\n")); - cache_fd = -1; - goto finished; - } - - sptr = rindex(ppath, '/'); - if (sptr == NULL) { - cache_fd = -1; - goto finished; - } - *sptr = 0; - if (ppath[0] == 0) { cache_fd = -1; goto finished; } @@ -576,22 +616,10 @@ int unlink_parent_dir_cache(const char *path) { char *ppath = NULL; char *cache_path = NULL; - char *sptr; int ret; - ppath = strdup(path); + ppath = get_parent_path(path); if (ppath == NULL) { - DEBUG(DEBUG_ERR,(__location__ " failed to strdup ppath\n")); - ret = -1; - goto finished; - } - sptr = rindex(ppath, '/'); - if (sptr == NULL) { - ret = -1; - goto finished; - } - *sptr = 0; - if (ppath[0] == 0) { ret = -1; goto finished; } @@ -619,9 +647,9 @@ finished: int lookup_attribute_in_parent(const char *path, struct stat *st) { char *ppath = NULL; + char *sptr; int cache_fd = -1; struct cached_dir_entry cache_dirent; - char *sptr; int ret = 0; ppath = strdup(path); @@ -1870,12 +1898,8 @@ static int remote_cache_mkdir(const char *path, mode_t mode) char *old_path = NULL; char *old_ppath = NULL; char *ppath = NULL; - char *sptr; - int perms; - struct stat st; uid_t uid = fuse_get_context()->uid; gid_t gid = fuse_get_context()->gid; - struct group_list gl; int ret; if (!read_write) { @@ -1883,22 +1907,12 @@ static int remote_cache_mkdir(const char *path, mode_t mode) goto finished; } - ppath = strdup(path); + ppath = get_parent_path(path); if (ppath == NULL) { - DEBUG(DEBUG_ERR,(__location__ " failed to strdup ppath\n")); ret = -ENOMEM; goto finished; } - sptr = rindex(ppath, '/'); - if (sptr == NULL) { - ret = -EACCES; - goto finished; - } - *sptr = 0; - if (ppath[0] == 0) { - ret = -EACCES; - goto finished; - } + if (asprintf(&old_path, "%s/%s", remote, path) == -1) { DEBUG(DEBUG_ERR,(__location__ " Failed to malloc old path\n")); ret = -ENOMEM; @@ -1919,23 +1933,8 @@ static int remote_cache_mkdir(const char *path, mode_t mode) DEBUG(DEBUG_DEBUG, (__location__ " MKDIR:%s mode:%o\n", path, (int)mode)); - /* read parent attributes from remote site */ - ret = get_group_list(uid, &gl); + ret = verify_permission(uid, gid, old_ppath, CAN_WRITE); if (ret != 0) { - DEBUG(DEBUG_ERR,(__location__ " Failed to read group list\n")); - ret = -EACCES; - goto finished; - } - bzero(&st, sizeof(st)); - ret = lstat(old_ppath, &st); - if (ret == -1) { - DEBUG(DEBUG_ERR, (__location__ " Failed to lstat(%s) %s\n", old_path, strerror(errno))); - ret = -EIO; - goto finished; - } - perms = check_permissions(&st, uid, gid, &gl); - if (!(perms & CAN_WRITE)) { - ret = -EACCES; goto finished; } @@ -1948,6 +1947,7 @@ static int remote_cache_mkdir(const char *path, mode_t mode) ret = chown(old_path, uid, gid); if (ret == -1) { DEBUG(DEBUG_ERR,(__location__ " Failed to chown() %s\n", old_path)); + //qqq if the chmod failed we must delete the directory ret = -errno; goto finished; } @@ -1979,14 +1979,24 @@ static int remote_cache_rmdir(const char *path) { char *new_path = NULL; char *old_path = NULL; + char *old_ppath = NULL; + char *ppath = NULL; int ret; + uid_t uid = fuse_get_context()->uid; + gid_t gid = fuse_get_context()->gid; if (!read_write) { ret = -EROFS; goto finished; } - if (asprintf(&old_path, "%s/%s", remote, path) == -1) { + ppath = get_parent_path(path); + if (ppath == NULL) { + ret = -ENOMEM; + goto finished; + } + + if (asprintf(&old_path, "%s/%s", remote, path) == -1) { DEBUG(DEBUG_ERR,(__location__ " Failed to malloc old path\n")); ret = -ENOMEM; goto finished; @@ -2000,13 +2010,11 @@ static int remote_cache_rmdir(const char *path) DEBUG(DEBUG_DEBUG, (__location__ " RMDIR:%s\n", path)); - ret = switch_to_real_user(); + ret = verify_permission(uid, gid, old_ppath, CAN_WRITE); if (ret != 0) { - DEBUG(DEBUG_ERR, (__location__ " SETEUID failed\n")); goto finished; } - ret = rmdir(old_path); if (ret != 0) { DEBUG(DEBUG_DEBUG,(__location__ " RMDIR %s failed with errno:%u\n", old_path, errno)); @@ -2017,12 +2025,16 @@ static int remote_cache_rmdir(const char *path) /* if the rmdir was successful we try to delete any local cached entries for this name */ - switch_back_to_root(); unlink_object(new_path); unlink_parent_dir_cache(new_path); finished: - switch_back_to_root(); + if (ppath != NULL) { + free(ppath); + } + if (old_ppath != NULL) { + free(old_ppath); + } if (old_path != NULL) { free(old_path); } @@ -2040,35 +2052,21 @@ static int remote_cache_unlink(const char *path) char *old_path = NULL; char *old_ppath = NULL; char *ppath = NULL; - char *sptr; int ret; - struct stat st; uid_t uid = fuse_get_context()->uid; gid_t gid = fuse_get_context()->gid; - struct group_list gl; - int perms; if (!read_write) { ret = -EROFS; goto finished; } - ppath = strdup(path); + ppath = get_parent_path(path); if (ppath == NULL) { - DEBUG(DEBUG_ERR,(__location__ " failed to strdup ppath\n")); ret = -ENOMEM; goto finished; } - sptr = rindex(ppath, '/'); - if (sptr == NULL) { - ret = -EACCES; - goto finished; - } - *sptr = 0; - if (ppath[0] == 0) { - ret = -EACCES; - goto finished; - } + if (asprintf(&new_path, "%s/%s", cache, path) == -1) { DEBUG(DEBUG_ERR,(__location__ " Failed to malloc new path\n")); ret = -ENOMEM; @@ -2088,23 +2086,8 @@ static int remote_cache_unlink(const char *path) DEBUG(DEBUG_DEBUG, (__location__ " UNLINK:%s\n", path)); - /* read parent attributes from remote site */ - ret = get_group_list(uid, &gl); + ret = verify_permission(uid, gid, old_ppath, CAN_WRITE); if (ret != 0) { - DEBUG(DEBUG_ERR,(__location__ " Failed to read group list\n")); - ret = -EACCES; - goto finished; - } - bzero(&st, sizeof(st)); - ret = lstat(old_ppath, &st); - if (ret == -1) { - DEBUG(DEBUG_ERR, (__location__ " Failed to lstat(%s) %s\n", old_path, strerror(errno))); - ret = -EIO; - goto finished; - } - perms = check_permissions(&st, uid, gid, &gl); - if (!(perms & CAN_WRITE)) { - ret = -EACCES; goto finished; } @@ -2257,37 +2240,21 @@ static int remote_cache_create(const char *path, mode_t mode, struct fuse_file_i char *old_path = NULL; char *old_ppath = NULL; char *ppath = NULL; - char *sptr; int ret; int fd; - struct stat st; uid_t uid = fuse_get_context()->uid; gid_t gid = fuse_get_context()->gid; - struct group_list gl; - int perms; if (!read_write) { ret = -EROFS; goto finished; } - ppath = strdup(path); + ppath = get_parent_path(path); if (ppath == NULL) { - DEBUG(DEBUG_ERR,(__location__ " failed to strdup ppath\n")); ret = -ENOMEM; goto finished; } - sptr = rindex(ppath, '/'); - if (sptr == NULL) { - ret = -EACCES; - goto finished; - } - *sptr = 0; - if (ppath[0] == 0) { - ret = -EACCES; - goto finished; - } - if (asprintf(&new_path, "%s/%s", cache, path) == -1) { DEBUG(DEBUG_ERR,(__location__ " Failed to malloc new path\n")); @@ -2307,26 +2274,10 @@ static int remote_cache_create(const char *path, mode_t mode, struct fuse_file_i DEBUG(DEBUG_DEBUG, (__location__ " CREATE %s mode %o\n", path, mode)); - ret = get_group_list(uid, &gl); + ret = verify_permission(uid, gid, old_ppath, CAN_WRITE); if (ret != 0) { - DEBUG(DEBUG_ERR,(__location__ " Failed to read group list\n")); - ret = -EACCES; goto finished; } - /* read parent attributes from remote site */ - bzero(&st, sizeof(st)); - ret = lstat(old_ppath, &st); - if (ret == -1) { - DEBUG(DEBUG_ERR, (__location__ " Failed to lstat(%s) %s\n", old_path, strerror(errno))); - ret = -EIO; - goto finished; - } - perms = check_permissions(&st, uid, gid, &gl); - if (!(perms & CAN_WRITE)) { - ret = -EACCES; - goto finished; - } - fd = creat(old_path, mode); if (fd == -1) { @@ -2336,10 +2287,10 @@ static int remote_cache_create(const char *path, mode_t mode, struct fuse_file_i } close(fd); - ret = chown(old_path, uid, gid); if (ret == -1) { DEBUG(DEBUG_ERR,(__location__ " Failed to chown() %s\n", old_path)); + //qqq delete the file if the chown failed check other uses ret = -errno; goto finished; } @@ -2432,11 +2383,8 @@ static int remote_cache_write_internal(const char *path, const char *buf, size_t char *old_path = NULL; int fd = -1; int ret; - int perms; - struct stat st; uid_t uid = fuse_get_context()->uid; gid_t gid = fuse_get_context()->gid; - struct group_list gl; if (asprintf(&new_path, "%s/%s", cache, path) == -1) { DEBUG(DEBUG_ERR,(__location__ " Failed to malloc new path\n")); @@ -2449,23 +2397,8 @@ static int remote_cache_write_internal(const char *path, const char *buf, size_t goto finished; } - ret = get_group_list(uid, &gl); + ret = verify_permission(uid, gid, old_path, CAN_WRITE); if (ret != 0) { - DEBUG(DEBUG_ERR,(__location__ " Failed to read group list\n")); - ret = -EACCES; - goto finished; - } - /* read attributes from remote site */ - bzero(&st, sizeof(st)); - ret = lstat(old_path, &st); - if (ret == -1) { - DEBUG(DEBUG_ERR, (__location__ " Failed to lstat(%s) %s\n", old_path, strerror(errno))); - ret = -EIO; - goto finished; - } - perms = check_permissions(&st, uid, gid, &gl); - if (!(perms & CAN_WRITE)) { - ret = -EACCES; goto finished; } @@ -2630,6 +2563,8 @@ static int remote_cache_ftruncate(const char *path, off_t offset, struct fuse_fi { char *new_path = NULL; char *old_path = NULL; + uid_t uid = fuse_get_context()->uid; + gid_t gid = fuse_get_context()->gid; int ret; if (!read_write) { @@ -2648,16 +2583,13 @@ static int remote_cache_ftruncate(const char *path, off_t offset, struct fuse_fi goto finished; } - DEBUG(DEBUG_DEBUG, (__location__ " FTRUNCATE %s offset %d\n", path, (int)offset)); - ret = switch_to_real_user(); + ret = verify_permission(uid, gid, old_path, CAN_WRITE); if (ret != 0) { - DEBUG(DEBUG_ERR, (__location__ " SETEUID failed\n")); goto finished; } - ret = truncate(old_path, offset); if (ret != 0) { DEBUG(DEBUG_DEBUG,(__location__ " FTRUNCATE %s offset %d failed with errno:%u\n", old_path, (int)offset, errno)); @@ -2668,12 +2600,10 @@ static int remote_cache_ftruncate(const char *path, off_t offset, struct fuse_fi /* if the ftruncate was successful we try to delete any local cached entries for this name */ - switch_back_to_root(); unlink_object(new_path); unlink_parent_dir_cache(new_path); finished: - switch_back_to_root(); if (old_path != NULL) { free(old_path); } -- 2.34.1