remove more switching between user ids
authorroot <root@rcn1.VSOFS1.COM>
Fri, 20 Mar 2009 05:08:07 +0000 (16:08 +1100)
committerroot <root@rcn1.VSOFS1.COM>
Fri, 20 Mar 2009 05:08:07 +0000 (16:08 +1100)
migrate/remote-cache.c

index 98ef48fed3cc912023045e9c8c2aadae2854bec1..3925a1b4067f08c613dd9ee790ccbc9fee1dc2f6 100644 (file)
@@ -347,6 +347,22 @@ int verify_permission(uid_t uid, gid_t gid, char *path, int required)
        return 0;
 }
 
+int get_owner(char *path, uid_t *uid)
+{
+       int ret;
+       struct stat st;
+
+       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;
+       }
+
+       *uid = st.st_uid;
+       return 0;
+}
+
 static void unlink_object(const char *path)
 {
        char *rmcmd = NULL;
@@ -524,12 +540,6 @@ char *get_parent_path(const char *path)
        }
        *sptr = 0;
 
-       if (ppath[0] == 0) {
-               free(ppath);
-               ppath = NULL;
-               goto finished;
-       }
-
 finished:
        return ppath;
 }
@@ -1837,6 +1847,7 @@ static int remote_cache_mknod(const char *path, mode_t mode, dev_t rdev)
 {
        char *new_path = NULL;
        char *old_path = NULL;
+       uid_t uid = fuse_get_context()->uid;
        int ret;
 
        if (!read_write) {      
@@ -1858,13 +1869,11 @@ static int remote_cache_mknod(const char *path, mode_t mode, dev_t rdev)
 
        DEBUG(DEBUG_DEBUG, (__location__ " MKNOD:%s mode:%o rdev:%x\n", path, (int)mode, (int)rdev));
 
-       ret = switch_to_real_user();
-       if (ret != 0) {
-               DEBUG(DEBUG_ERR, (__location__ " SETEUID failed\n"));
+       if (uid != 0) {
+               ret = -EPERM;
                goto finished;
        }
 
-
        ret = mknod(old_path, mode, rdev);
        if (ret != 0) {
                DEBUG(DEBUG_DEBUG,(__location__ " MKNOD %s mode:%o rdev:%x failed with errno:%u\n", old_path, mode, (int)rdev, errno));
@@ -1875,12 +1884,10 @@ static int remote_cache_mknod(const char *path, mode_t mode, dev_t rdev)
        /* if the mknod 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);
        }
@@ -2124,6 +2131,8 @@ static int remote_cache_chmod(const char *path, mode_t mode)
 {
        char *new_path = NULL;
        char *old_path = NULL;
+       uid_t obj_uid;
+       uid_t uid = fuse_get_context()->uid;
        int ret;
 
        if (!read_write) {
@@ -2142,15 +2151,18 @@ static int remote_cache_chmod(const char *path, mode_t mode)
                goto finished;
        }
 
-
        DEBUG(DEBUG_DEBUG, (__location__ " CHMOD:%s mode:%o\n", path, mode));
 
-       ret = switch_to_real_user();
+       ret = get_owner(old_path, &obj_uid);
        if (ret != 0) {
-               DEBUG(DEBUG_ERR, (__location__ " SETEUID failed\n"));
+               DEBUG(DEBUG_ERR, (__location__ " get_owner failed\n"));
                goto finished;
        }
 
+       if ((uid != obj_uid) && (uid != 0)) {
+               ret = -EPERM;
+               goto finished;
+       }
 
        ret = chmod(old_path, mode);
        if (ret != 0) {
@@ -2162,12 +2174,10 @@ static int remote_cache_chmod(const char *path, mode_t mode)
        /* if the chmod 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);
        }
@@ -2324,6 +2334,8 @@ static int remote_cache_utime(const char *path, struct utimbuf *times)
 {
        char *new_path = NULL;
        char *old_path = NULL;
+       uid_t obj_uid;
+       uid_t uid = fuse_get_context()->uid;
        int ret;
 
        if (!read_write) {
@@ -2345,12 +2357,16 @@ static int remote_cache_utime(const char *path, struct utimbuf *times)
 
        DEBUG(DEBUG_DEBUG, (__location__ " UTIME %s\n", path));
 
-       ret = switch_to_real_user();
+       ret = get_owner(old_path, &obj_uid);
        if (ret != 0) {
-               DEBUG(DEBUG_ERR, (__location__ " SETEUID failed\n"));
+               DEBUG(DEBUG_ERR, (__location__ " get_owner failed\n"));
                goto finished;
        }
 
+       if ((uid != obj_uid) && (uid != 0)) {
+               ret = -EPERM;
+               goto finished;
+       }
 
        ret = utime(old_path, times);
        if (ret != 0) {
@@ -2362,12 +2378,10 @@ static int remote_cache_utime(const char *path, struct utimbuf *times)
        /* if the utime 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);
        }
@@ -2506,6 +2520,8 @@ static int remote_cache_truncate(const char *path, off_t offset)
 {
        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) {
@@ -2527,13 +2543,11 @@ static int remote_cache_truncate(const char *path, off_t offset)
 
        DEBUG(DEBUG_DEBUG, (__location__ " TRUNCATE %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__ " TRUNCATE %s offset %d failed with errno:%u\n", old_path, (int)offset, errno));
@@ -2544,12 +2558,10 @@ static int remote_cache_truncate(const char *path, off_t offset)
        /* if the truncate 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);
        }