Diff

Differences From Artifact [227a45ec34]:

To Artifact [9cae19dbb7]:


     1      1   #define FUSE_USE_VERSION 26
     2      2   
            3  +#include <sys/fsuid.h>
     3      4   #include <sys/types.h>
     4      5   #include <pthread.h>
     5      6   #include <string.h>
     6      7   #include <stdarg.h>
     7      8   #include <stdlib.h>
     8      9   #include <unistd.h>
     9     10   #include <errno.h>
................................................................................
   297    298   		/* Unable to lookup user for some reason */
   298    299   		/* Return an unprivileged user ID */
   299    300   		return(1);
   300    301   	}
   301    302   
   302    303   	return(ctx->uid);
   303    304   }
          305  +
          306  +/*
          307  + * Determine the GID for the user making the current FUSE filesystem request.
          308  + * This will be used to lookup the user's home directory so we can search for
          309  + * locally modified files.
          310  + */
          311  +static gid_t appfs_get_fsgid(void) {
          312  +	struct fuse_context *ctx;
          313  +
          314  +	if (!appfs_fuse_started) {
          315  +		return(getgid());
          316  +	}
          317  +
          318  +	ctx = fuse_get_context();
          319  +	if (ctx == NULL) {
          320  +		/* Unable to lookup user for some reason */
          321  +		/* Return an unprivileged user ID */
          322  +		return(1);
          323  +	}
          324  +
          325  +	return(ctx->gid);
          326  +}
          327  +
          328  +static void appfs_simulate_user_fs_enter(void) {
          329  +	setfsuid(appfs_get_fsuid());
          330  +	setfsgid(appfs_get_fsgid());
          331  +}
          332  +
          333  +static void appfs_simulate_user_fs_leave(void) {
          334  +	setfsuid(0);
          335  +	setfsgid(0);
          336  +}
   304    337   
   305    338   /*
   306    339    * Look up the home directory for a given UID
   307    340    *        Returns a C string containing the user's home directory or NULL if
   308    341    *        the user's home directory does not exist or is not correctly
   309    342    *        configured
   310    343    */
................................................................................
   357    390   
   358    391   /*
   359    392    * Tcl interface to get the home directory for the user making the "current"
   360    393    * FUSE I/O request
   361    394    */
   362    395   static int tcl_appfs_get_homedir(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
   363    396   	char *homedir;
          397  +	Tcl_Obj *homedir_obj;
          398  +	uid_t fsuid;
          399  +	static __thread Tcl_Obj *last_homedir_obj = NULL;
          400  +	static __thread uid_t last_fsuid = -1;
   364    401   
   365    402           if (objc != 1) {
   366    403                   Tcl_WrongNumArgs(interp, 1, objv, NULL);
   367    404                   return(TCL_ERROR);
   368    405           }
   369    406   
   370         -	homedir = appfs_get_homedir(appfs_get_fsuid());
          407  +	fsuid = appfs_get_fsuid();
   371    408   
   372         -	if (homedir == NULL) {
   373         -		return(TCL_ERROR);
          409  +	if (fsuid == last_fsuid && last_homedir_obj != NULL) {
          410  +		homedir_obj = last_homedir_obj;
          411  +	} else {
          412  +		if (last_homedir_obj != NULL) {
          413  +			Tcl_DecrRefCount(last_homedir_obj);
          414  +		}
          415  +
          416  +		homedir = appfs_get_homedir(appfs_get_fsuid());
          417  +
          418  +		if (homedir == NULL) {
          419  +			return(TCL_ERROR);
          420  +		}
          421  +
          422  +		homedir_obj = Tcl_NewStringObj(homedir, -1);
          423  +
          424  +		free(homedir);
          425  +
          426  +		last_homedir_obj = homedir_obj;
          427  +		last_fsuid = fsuid;
          428  +
          429  +		Tcl_IncrRefCount(last_homedir_obj);
   374    430   	}
   375    431   
   376         -        Tcl_SetObjResult(interp, Tcl_NewStringObj(homedir, -1));
   377         -
   378         -	free(homedir);
          432  +       	Tcl_SetObjResult(interp, homedir_obj);
   379    433   
   380    434           return(TCL_OK);
   381    435   }
   382    436   
   383    437   /*
   384    438    * Generate an inode for a given path.  The inode should be computed in such
   385    439    * a way that it is unlikely to be duplicated and remains the same for a given
................................................................................
   628    682   
   629    683   	stbuf->st_mtime = pathinfo.time;
   630    684   	stbuf->st_ctime = pathinfo.time;
   631    685   	stbuf->st_atime = pathinfo.time;
   632    686   	stbuf->st_ino   = pathinfo.inode;
   633    687   	stbuf->st_mode  = 0;
   634    688   	stbuf->st_uid   = appfs_get_fsuid();
          689  +	stbuf->st_gid   = appfs_get_fsgid();
   635    690   
   636    691   	switch (pathinfo.type) {
   637    692   		case APPFS_PATHTYPE_DIRECTORY:
   638    693   			stbuf->st_mode = S_IFDIR | 0555;
   639    694   			stbuf->st_nlink = 2 + pathinfo.typeinfo.dir.childcount;
   640    695   			break;
   641    696   		case APPFS_PATHTYPE_FILE:
................................................................................
   742    797   		return(-EISDIR);
   743    798   	}
   744    799   
   745    800   	interp = appfs_TclInterp();
   746    801   	if (interp == NULL) {
   747    802   		return(-EIO);
   748    803   	}
          804  +
          805  +	appfs_simulate_user_fs_enter();
   749    806   
   750    807   	tcl_ret = appfs_Tcl_Eval(interp, 3, "::appfs::openpath", path, mode);
   751    808   	if (tcl_ret != TCL_OK) {
          809  +		appfs_simulate_user_fs_leave();
          810  +
   752    811   		APPFS_DEBUG("::appfs::openpath(%s, %s) failed.", path, mode);
   753    812   		APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp));
   754    813   
   755    814   		return(-EIO);
   756    815   	}
   757    816   
   758    817   	real_path = Tcl_GetStringResult(interp);
   759    818   	if (real_path == NULL) {
          819  +		appfs_simulate_user_fs_leave();
          820  +
   760    821   		return(-EIO);
   761    822   	}
   762    823   
   763    824   	APPFS_DEBUG("Translated request to open %s to opening %s (mode = \"%s\")", path, real_path, mode);
   764    825   
   765    826   	fh = open(real_path, fi->flags, 0600);
          827  +
          828  +	appfs_simulate_user_fs_leave();
          829  +
   766    830   	if (fh < 0) {
   767    831   		return(-EIO);
   768    832   	}
   769    833   
   770    834   	fi->fh = fh;
   771    835   
   772    836   	return(0);
................................................................................
   824    888   	if ((mode & S_IFCHR) == S_IFCHR) {
   825    889   		return(-EPERM);
   826    890   	}
   827    891   
   828    892   	if ((mode & S_IFBLK) == S_IFBLK) {
   829    893   		return(-EPERM);
   830    894   	}
          895  +
          896  +	appfs_simulate_user_fs_enter();
   831    897   
   832    898   	real_path = appfs_prepare_to_create(path);
   833    899   	if (real_path == NULL) {
          900  +		appfs_simulate_user_fs_leave();
          901  +
   834    902   		return(-EIO);
   835    903   	}
   836    904   
   837    905   	mknod_ret = mknod(real_path, mode, device);
          906  +
          907  +	appfs_simulate_user_fs_leave();
   838    908   
   839    909   	free(real_path);
   840    910   
   841    911   	if (mknod_ret != 0) {
   842    912   		return(errno * -1);
   843    913   	}
   844    914   
................................................................................
   854    924   	if ((mode & S_IFCHR) == S_IFCHR) {
   855    925   		return(-EPERM);
   856    926   	}
   857    927   
   858    928   	if ((mode & S_IFBLK) == S_IFBLK) {
   859    929   		return(-EPERM);
   860    930   	}
          931  +
          932  +	appfs_simulate_user_fs_enter();
   861    933   
   862    934   	real_path = appfs_prepare_to_create(path);
   863    935   	if (real_path == NULL) {
          936  +		appfs_simulate_user_fs_leave();
          937  +
   864    938   		return(-EIO);
   865    939   	}
   866    940   
   867    941   	fd = creat(real_path, mode);
          942  +
          943  +	appfs_simulate_user_fs_leave();
   868    944   
   869    945   	free(real_path);
   870    946   
   871    947   	if (fd < 0) {
   872    948   		return(errno * -1);
   873    949   	}
   874    950   
................................................................................
   883    959   
   884    960   	APPFS_DEBUG("Enter (path = %s, ...)", path);
   885    961   
   886    962   	real_path = appfs_localpath(path);
   887    963   	if (real_path == NULL) {
   888    964   		return(-EIO);
   889    965   	}
          966  +
          967  +	appfs_simulate_user_fs_enter();
   890    968   
   891    969   	truncate_ret = truncate(real_path, size);
          970  +
          971  +	appfs_simulate_user_fs_leave();
   892    972   
   893    973   	free(real_path);
   894    974   
   895    975   	if (truncate_ret != 0) {
   896    976   		return(errno * -1);
   897    977   	}
   898    978   
................................................................................
   905    985   
   906    986   	APPFS_DEBUG("Enter (path = %s, ...)", path);
   907    987   
   908    988   	interp = appfs_TclInterp();
   909    989   	if (interp == NULL) {
   910    990   		return(-EIO);
   911    991   	}
          992  +
          993  +	appfs_simulate_user_fs_enter();
   912    994   
   913    995   	tcl_ret = appfs_Tcl_Eval(interp, 2, "::appfs::unlinkpath", path);
          996  +
          997  +	appfs_simulate_user_fs_leave();
          998  +
   914    999   	if (tcl_ret != TCL_OK) {
   915   1000   		APPFS_DEBUG("::appfs::unlinkpath(%s) failed.", path);
   916   1001   		APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp));
   917   1002   
   918   1003   		return(-EIO);
   919   1004   	}
   920   1005   
................................................................................
   922   1007   }
   923   1008   
   924   1009   static int appfs_fuse_mkdir(const char *path, mode_t mode) {
   925   1010   	char *real_path;
   926   1011   	int mkdir_ret;
   927   1012   
   928   1013   	APPFS_DEBUG("Enter (path = %s, ...)", path);
         1014  +
         1015  +	appfs_simulate_user_fs_enter();
   929   1016   
   930   1017   	real_path = appfs_prepare_to_create(path);
   931   1018   	if (real_path == NULL) {
         1019  +		appfs_simulate_user_fs_leave();
         1020  +
   932   1021   		return(-EIO);
   933   1022   	}
   934   1023   
   935   1024   	mkdir_ret = mkdir(real_path, mode);
         1025  +
         1026  +	appfs_simulate_user_fs_leave();
   936   1027   
   937   1028   	free(real_path);
   938   1029   
   939   1030   	if (mkdir_ret != 0) {
   940   1031   		if (errno != EEXIST) {
   941   1032   			return(errno * -1);
   942   1033   		}
................................................................................
   952   1043   
   953   1044   	APPFS_DEBUG("Enter (path = %s, ...)", path);
   954   1045   
   955   1046   	interp = appfs_TclInterp();
   956   1047   	if (interp == NULL) {
   957   1048   		return(-EIO);
   958   1049   	}
         1050  +
         1051  +	appfs_simulate_user_fs_enter();
   959   1052   
   960   1053   	tcl_ret = appfs_Tcl_Eval(interp, 3, "::appfs::openpath", path, "write");
   961   1054   	if (tcl_ret != TCL_OK) {
         1055  +		appfs_simulate_user_fs_leave();
         1056  +
   962   1057   		APPFS_DEBUG("::appfs::openpath(%s, %s) failed.", path, "write");
   963   1058   		APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp));
   964   1059   
   965   1060   		return(-EIO);
   966   1061   	}
   967   1062   
   968   1063   	real_path = Tcl_GetStringResult(interp);
   969   1064   	if (real_path == NULL) {
         1065  +		appfs_simulate_user_fs_leave();
         1066  +
   970   1067   		return(-EIO);
   971   1068   	}
   972   1069   
   973   1070   	chmod_ret = chmod(real_path, mode);
         1071  +
         1072  +	appfs_simulate_user_fs_leave();
   974   1073   
   975   1074   	return(chmod_ret);
   976   1075   }
   977   1076   
   978   1077   /*
   979   1078    * SQLite3 mode: Execute raw SQL and return success or failure
   980   1079    */