Overview
Comment: | Allow administrators to provide additional/replaced permissions for files, fixed suidRoot setting |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: | e9fcc6d8f52f28a19bad96be870994ef91b05e5a |
User & Date: | rkeene on 2015-03-19 16:09:20 |
Other Links: | manifest | tags |
Context
2015-03-20
| ||
01:46 | Updated to lowercase permissions read from the database, for security check-in: 0ab26b4975 user: rkeene tags: trunk | |
2015-03-19
| ||
16:09 | Allow administrators to provide additional/replaced permissions for files, fixed suidRoot setting check-in: e9fcc6d8f5 user: rkeene tags: trunk | |
15:43 | Updated to indicate local files are not world-accessible (good idea ?) check-in: 9be4aa6a4a user: rkeene tags: trunk | |
Changes
Modified appfsd.c from [3e9adabf49] to [fe7e6328bd].
139 139 unsigned long long inode; 140 140 union { 141 141 struct { 142 142 int childcount; 143 143 } dir; 144 144 struct { 145 145 int executable; 146 - int suid; 146 + int suidRoot; 147 147 int worldaccessible; 148 148 off_t size; 149 149 } file; 150 150 struct { 151 151 off_t size; 152 152 char source[256]; 153 153 } symlink; ................................................................................ 932 932 } 933 933 934 934 break; 935 935 case 'f': /* file */ 936 936 pathinfo->type = APPFS_PATHTYPE_FILE; 937 937 pathinfo->typeinfo.file.size = 0; 938 938 pathinfo->typeinfo.file.executable = 0; 939 - pathinfo->typeinfo.file.suid = 0; 939 + pathinfo->typeinfo.file.suidRoot = 0; 940 940 pathinfo->typeinfo.file.worldaccessible = 0; 941 941 942 942 Tcl_DictObjGet(interp, attrs_dict, attr_key_size, &attr_value); 943 943 if (attr_value != NULL) { 944 944 tcl_ret = Tcl_GetWideIntFromObj(NULL, attr_value, &attr_value_wide); 945 945 if (tcl_ret == TCL_OK) { 946 946 pathinfo->typeinfo.file.size = attr_value_wide; ................................................................................ 953 953 for (attr_value_str_i = &attr_value_str[0]; *attr_value_str_i != '\0'; attr_value_str_i++) { 954 954 switch (*attr_value_str_i) { 955 955 case 'x': 956 956 pathinfo->typeinfo.file.executable = 1; 957 957 958 958 break; 959 959 case 'U': 960 - pathinfo->typeinfo.file.suid = 1; 960 + pathinfo->typeinfo.file.suidRoot = 1; 961 961 962 962 break; 963 963 case '-': 964 964 pathinfo->typeinfo.file.worldaccessible = 1; 965 965 966 966 break; 967 967 } ................................................................................ 1148 1148 memcpy(buf, pathinfo.typeinfo.symlink.source, strlen(pathinfo.typeinfo.symlink.source) + 1); 1149 1149 1150 1150 return(0); 1151 1151 } 1152 1152 1153 1153 static int appfs_fuse_getattr(const char *path, struct stat *stbuf) { 1154 1154 struct appfs_pathinfo pathinfo; 1155 + int changeOwnerToUserIfPackaged; 1155 1156 int retval; 1156 1157 1157 1158 retval = 0; 1158 1159 1159 1160 APPFS_DEBUG("Enter (path = %s, ...)", path); 1160 1161 1161 1162 #if (defined(DEBUG) && defined(APPFS_EXIT_PATH)) || defined(APPFS_EXIT_PATH_ENABLE_MAJOR_SECURITY_HOLE) ................................................................................ 1186 1187 1187 1188 stbuf->st_mtime = pathinfo.time; 1188 1189 stbuf->st_ctime = pathinfo.time; 1189 1190 stbuf->st_atime = pathinfo.time; 1190 1191 stbuf->st_ino = pathinfo.inode; 1191 1192 stbuf->st_mode = 0; 1192 1193 1194 + changeOwnerToUserIfPackaged = 1; 1195 + 1193 1196 switch (pathinfo.type) { 1194 1197 case APPFS_PATHTYPE_DIRECTORY: 1195 1198 stbuf->st_mode = S_IFDIR | 0555; 1196 1199 stbuf->st_nlink = 2 + pathinfo.typeinfo.dir.childcount; 1197 1200 break; 1198 1201 case APPFS_PATHTYPE_FILE: 1199 - if (pathinfo.typeinfo.file.executable) { 1200 - stbuf->st_mode = S_IFREG | 0555; 1201 - } else { 1202 1202 stbuf->st_mode = S_IFREG | 0444; 1203 + 1204 + if (pathinfo.typeinfo.file.executable) { 1205 + stbuf->st_mode |= 0111; 1203 1206 } 1204 1207 1205 - if (pathinfo.typeinfo.file.suid) { 1206 - stbuf->st_mode = S_IFREG | 04000; 1208 + if (pathinfo.typeinfo.file.suidRoot) { 1209 + changeOwnerToUserIfPackaged = 0; 1210 + 1211 + stbuf->st_mode |= 04000; 1207 1212 } 1208 1213 1209 1214 if (pathinfo.typeinfo.file.worldaccessible) { 1210 1215 stbuf->st_mode &= ~077; 1211 1216 } 1212 1217 1213 1218 stbuf->st_nlink = 1; ................................................................................ 1235 1240 break; 1236 1241 case APPFS_PATHTYPE_INVALID: 1237 1242 retval = -EIO; 1238 1243 1239 1244 break; 1240 1245 } 1241 1246 1242 - if (pathinfo.packaged) { 1247 + if (pathinfo.packaged && changeOwnerToUserIfPackaged) { 1243 1248 stbuf->st_uid = appfs_get_fsuid(); 1244 1249 stbuf->st_gid = appfs_get_fsgid(); 1245 1250 stbuf->st_mode |= 0200; 1246 1251 } 1247 1252 1248 1253 return(retval); 1249 1254 } ................................................................................ 2006 2011 ** Add FUSE arguments which we always supply 2007 2012 **/ 2008 2013 fuse_opt_add_arg(args, "-odefault_permissions,fsname=appfs,subtype=appfsd,use_ino,kernel_cache,entry_timeout=0,attr_timeout=0,big_writes,intr,hard_remove"); 2009 2014 2010 2015 if (getuid() == 0) { 2011 2016 fuse_opt_parse(args, NULL, NULL, NULL); 2012 2017 fuse_opt_add_arg(args, "-oallow_other"); 2018 + 2019 + /* 2020 + * This should generally be avoided, but if there are security 2021 + * concerns suid can be disabled completely on the commandline 2022 + */ 2023 + fuse_opt_parse(args, NULL, NULL, NULL); 2024 + fuse_opt_add_arg(args, "-osuid"); 2013 2025 } 2014 2026 2015 2027 while ((ch = getopt(argc, argv, "dfshvo:")) != -1) { 2016 2028 switch (ch) { 2017 2029 case 'v': 2018 2030 /* Ignored */ 2019 2031 break;
Modified appfsd.tcl from [c5b01df3b2] to [ca14ca67ab].
36 36 return "http://$hostname/appfs/$method/$hash" 37 37 } 38 38 39 39 # User-replaceable function get the home directory of the current user 40 40 proc get_homedir {} { 41 41 return [::appfsd::get_homedir] 42 42 } 43 + 44 + # User-replacable function to update permissions 45 + proc change_perms {file perms} { 46 + if {[info exists ::appfs::user::add_perms($file)]} { 47 + append perms $::appfs::user::add_perms($file) 48 + } 49 + 50 + return $perms 51 + } 43 52 } 44 53 45 54 namespace eval ::appfs { 46 55 variable cachedir "/tmp/appfs-cache" 47 56 variable ttl 3600 48 57 variable nttl 60 49 58 variable trusted_cas [list] ................................................................................ 751 760 "directory" { 752 761 set retval(type) "directory" 753 762 set retval(childcount) [llength [getchildren $path]] 754 763 } 755 764 "file" { 756 765 set retval(type) "file" 757 766 set retval(size) $localpathinfo(size) 767 + 768 + # Once the user writes to a file, all its other 769 + # attributes (such as suid) are lost 770 + 758 771 _as_user { 759 772 if {[file executable $localpath]} { 760 773 set retval(perms) "x-" 761 774 } else { 762 775 set retval(perms) "-" 763 776 } 764 777 } ................................................................................ 789 802 set file [lindex $work end] 790 803 791 804 if {$directory == "" && $file == ""} { 792 805 array set retval [list type directory] 793 806 } 794 807 795 808 ::appfs::db eval {SELECT type, time, source, size, perms FROM files WHERE package_sha1 = $pathinfo(package_sha1) AND file_directory = $directory AND file_name = $file;} retval {} 809 + 810 + # Allow an administrator to supply additional permissions to remote files 811 + if {[info exists retval(perms)]} { 812 + set retval(perms) [::appfs::user::change_perms $path $retval(perms)] 813 + } 796 814 797 815 if {[info exists retval(type)] && $retval(type) == "directory"} { 798 816 set retval(childcount) [llength [getchildren $path]] 799 817 } 800 818 801 819 unset -nocomplain retval(*) 802 820 }