diff options
author | Jeremy Allison <jra@samba.org> | 2001-04-14 00:19:12 +0000 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2001-04-14 00:19:12 +0000 |
commit | 53850c51caf1c4d53ff285b2e5505e0615beeeee (patch) | |
tree | 03e7d594efd340da6909e0efa2cf3dd05b6a610b | |
parent | 9444e9d9f350961b594a1acbe7a7652d97faec0a (diff) | |
download | samba-53850c51caf1c4d53ff285b2e5505e0615beeeee.tar.gz samba-53850c51caf1c4d53ff285b2e5505e0615beeeee.tar.bz2 samba-53850c51caf1c4d53ff285b2e5505e0615beeeee.zip |
configure:
configure.in:
include/config.h.in:
include/profile.h:
smbd/vfs-wrap.c:
smbd/vfs.c:
Added fchmod and fchown to VFS (sorry Gerald - but we needed them anyway).
smbd/dosmode.c:
smbd/files.c:
printing/printfsp.c:
smbd/close.c:
smbd/open.c:
Fixed "dos filemode" correctly so there are no race conditions. Forces test
of open of file O_WRONLY before allowing fchmod as root. Afterwards, calls
standard close function that preserves POSIX locks due to POSIX-me-harder
braindamage. :-). Andrew please review this code.
Also - in removing the tmpdir param in smbrun an extra NULL parameter
was missed in each print_run_command() call (which is a varargs fn.).
Now fixed.
Jeremy.
(This used to be commit 32397e5bc6d995ce7ca37c82d6aedc1e5b1b6fbd)
-rwxr-xr-x | source3/configure | 2 | ||||
-rw-r--r-- | source3/configure.in | 2 | ||||
-rw-r--r-- | source3/include/config.h.in | 6 | ||||
-rw-r--r-- | source3/include/profile.h | 6 | ||||
-rw-r--r-- | source3/include/proto.h | 6 | ||||
-rw-r--r-- | source3/include/vfs.h | 2 | ||||
-rw-r--r-- | source3/printing/print_generic.c | 22 | ||||
-rw-r--r-- | source3/printing/printfsp.c | 2 | ||||
-rw-r--r-- | source3/smbd/close.c | 2 | ||||
-rw-r--r-- | source3/smbd/dosmode.c | 26 | ||||
-rw-r--r-- | source3/smbd/files.c | 5 | ||||
-rw-r--r-- | source3/smbd/open.c | 54 | ||||
-rw-r--r-- | source3/smbd/vfs-wrap.c | 41 | ||||
-rw-r--r-- | source3/smbd/vfs.c | 10 |
14 files changed, 144 insertions, 42 deletions
diff --git a/source3/configure b/source3/configure index 1288634fe6..7cf0e29407 100755 --- a/source3/configure +++ b/source3/configure @@ -5100,7 +5100,7 @@ else RUNPROG="" fi -for ac_func in waitpid getcwd strdup strtoul strerror chown chmod chroot +for ac_func in waitpid getcwd strdup strtoul strerror chown fchown chmod fchmod chroot do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 echo "configure:5107: checking for $ac_func" >&5 diff --git a/source3/configure.in b/source3/configure.in index a201823295..c8270d2d5c 100644 --- a/source3/configure.in +++ b/source3/configure.in @@ -471,7 +471,7 @@ else RUNPROG="" fi -AC_CHECK_FUNCS(waitpid getcwd strdup strtoul strerror chown chmod chroot) +AC_CHECK_FUNCS(waitpid getcwd strdup strtoul strerror chown fchown chmod fchmod chroot) AC_CHECK_FUNCS(fstat strchr utime utimes getrlimit fsync bzero memset) AC_CHECK_FUNCS(memmove vsnprintf snprintf setsid glob strpbrk pipe crypt16 getauthuid) AC_CHECK_FUNCS(strftime sigprocmask sigblock sigaction innetgr setnetgrent getnetgrent endnetgrent) diff --git a/source3/include/config.h.in b/source3/include/config.h.in index a60d927976..b13f465691 100644 --- a/source3/include/config.h.in +++ b/source3/include/config.h.in @@ -466,6 +466,12 @@ /* Define if you have the execl function. */ #undef HAVE_EXECL +/* Define if you have the fchmod function. */ +#undef HAVE_FCHMOD + +/* Define if you have the fchown function. */ +#undef HAVE_FCHOWN + /* Define if you have the fcvt function. */ #undef HAVE_FCVT diff --git a/source3/include/profile.h b/source3/include/profile.h index b05e1fd9bb..5916614fb7 100644 --- a/source3/include/profile.h +++ b/source3/include/profile.h @@ -35,7 +35,7 @@ enum flush_reason_enum { SEEK_FLUSH, READ_FLUSH, WRITE_FLUSH, READRAW_FLUSH, #define PROF_SHMEM_KEY ((key_t)0x07021999) #define PROF_SHM_MAGIC 0x6349985 -#define PROF_SHM_VERSION 3 +#define PROF_SHM_VERSION 4 /* time values in the following structure are in microseconds */ @@ -80,8 +80,12 @@ struct profile_stats { unsigned syscall_unlink_time; unsigned syscall_chmod_count; unsigned syscall_chmod_time; + unsigned syscall_fchmod_count; + unsigned syscall_fchmod_time; unsigned syscall_chown_count; unsigned syscall_chown_time; + unsigned syscall_fchown_count; + unsigned syscall_fchown_time; unsigned syscall_chdir_count; unsigned syscall_chdir_time; unsigned syscall_getwd_count; diff --git a/source3/include/proto.h b/source3/include/proto.h index 890c2dcf60..5d7398b23f 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -3951,7 +3951,7 @@ BOOL check_name(char *name,connection_struct *conn); /*The following definitions come from smbd/files.c */ -files_struct *file_new(void ); +files_struct *file_new(connection_struct *conn); void file_close_conn(connection_struct *conn); void file_init(void); void file_close_user(int vuid); @@ -4048,6 +4048,8 @@ files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_S int share_mode,int ofun, mode_t mode,int oplock_request, int *Access,int *action); files_struct *open_file_stat(connection_struct *conn, char *fname, SMB_STRUCT_STAT *psbuf, int smb_ofun, int *action); +files_struct *open_file_fchmod(connection_struct *conn, char *fname, SMB_STRUCT_STAT *psbuf); +int close_file_fchmod(files_struct *fsp); files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_STAT *psbuf, int smb_ofun, mode_t unixmode, int *action); BOOL check_file_sharing(connection_struct *conn,char *fname, BOOL rename_op); @@ -4311,7 +4313,9 @@ int vfswrap_fstat(files_struct *fsp, int fd, SMB_STRUCT_STAT *sbuf); int vfswrap_lstat(connection_struct *conn, char *path, SMB_STRUCT_STAT *sbuf); int vfswrap_unlink(connection_struct *conn, char *path); int vfswrap_chmod(connection_struct *conn, char *path, mode_t mode); +int vfswrap_fchmod(files_struct *fsp, int fd, mode_t mode); int vfswrap_chown(connection_struct *conn, char *path, uid_t uid, gid_t gid); +int vfswrap_fchown(files_struct *fsp, int fd, uid_t uid, gid_t gid); int vfswrap_chdir(connection_struct *conn, char *path); char *vfswrap_getwd(connection_struct *conn, char *path); int vfswrap_utime(connection_struct *conn, char *path, struct utimbuf *times); diff --git a/source3/include/vfs.h b/source3/include/vfs.h index 9ca4bde0c5..51f3df1ec9 100644 --- a/source3/include/vfs.h +++ b/source3/include/vfs.h @@ -78,7 +78,9 @@ struct vfs_ops { int (*lstat)(struct connection_struct *conn, char *path, SMB_STRUCT_STAT *sbuf); int (*unlink)(struct connection_struct *conn, char *path); int (*chmod)(struct connection_struct *conn, char *path, mode_t mode); + int (*fchmod)(struct files_struct *fsp, int fd, mode_t mode); int (*chown)(struct connection_struct *conn, char *path, uid_t uid, gid_t gid); + int (*fchown)(struct files_struct *fsp, int fd, uid_t uid, gid_t gid); int (*chdir)(struct connection_struct *conn, char *path); char *(*getwd)(struct connection_struct *conn, char *buf); int (*utime)(struct connection_struct *conn, char *path, struct utimbuf *times); diff --git a/source3/printing/print_generic.c b/source3/printing/print_generic.c index eff394593c..ef38d26493 100644 --- a/source3/printing/print_generic.c +++ b/source3/printing/print_generic.c @@ -104,7 +104,7 @@ static int generic_job_delete(int snum, struct printjob *pjob) slprintf(jobstr, sizeof(jobstr)-1, "%d", pjob->sysjob); return print_run_command( snum, - lp_lprmcommand(snum), NULL, NULL, + lp_lprmcommand(snum), NULL, "%j", jobstr, "%T", http_timestring(pjob->starttime), NULL); @@ -120,7 +120,7 @@ static int generic_job_pause(int snum, struct printjob *pjob) /* need to pause the spooled entry */ slprintf(jobstr, sizeof(jobstr)-1, "%d", pjob->sysjob); return print_run_command(snum, - lp_lppausecommand(snum), NULL, NULL, + lp_lppausecommand(snum), NULL, "%j", jobstr, NULL); } @@ -135,7 +135,7 @@ static int generic_job_resume(int snum, struct printjob *pjob) /* need to pause the spooled entry */ slprintf(jobstr, sizeof(jobstr)-1, "%d", pjob->sysjob); return print_run_command(snum, - lp_lpresumecommand(snum), NULL, NULL, + lp_lpresumecommand(snum), NULL, "%j", jobstr, NULL); } @@ -172,7 +172,7 @@ static int generic_job_submit(int snum, struct printjob *pjob) /* send it to the system spooler */ ret = print_run_command(snum, - lp_printcommand(snum), NULL, NULL, + lp_printcommand(snum), NULL, "%s", p, "%J", jobname, "%f", p, @@ -189,11 +189,8 @@ get the current list of queued jobs ****************************************************************************/ static int generic_queue_get(int snum, print_queue_struct **q, print_status_struct *status) { - char *path = lp_pathname(snum); - char *cmd = lp_lpqcommand(snum); char **qlines; int fd; - pstring tmp_file; int numlines, i, qcount; print_queue_struct *queue = NULL; fstring printer_name; @@ -202,10 +199,7 @@ static int generic_queue_get(int snum, print_queue_struct **q, print_status_stru fstrcpy(printer_name, lp_servicename(snum)); dos_to_unix(printer_name, True); - slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smblpq.%d", path, sys_getpid()); - - unlink(tmp_file); - print_run_command(snum, cmd, &fd, tmp_file, NULL); + print_run_command(snum, lp_lpqcommand(snum), &fd, NULL); if (fd == -1) { DEBUG(5,("generic_queue_get: Can't read print queue status for printer %s\n", @@ -243,8 +237,7 @@ static int generic_queue_get(int snum, print_queue_struct **q, print_status_stru ****************************************************************************/ static int generic_queue_pause(int snum) { - return print_run_command(snum, lp_queuepausecommand(snum), NULL, NULL, - NULL); + return print_run_command(snum, lp_queuepausecommand(snum), NULL, NULL); } /**************************************************************************** @@ -252,6 +245,5 @@ static int generic_queue_pause(int snum) ****************************************************************************/ static int generic_queue_resume(int snum) { - return print_run_command(snum, lp_queueresumecommand(snum), NULL, NULL, - NULL); + return print_run_command(snum, lp_queueresumecommand(snum), NULL, NULL); } diff --git a/source3/printing/printfsp.c b/source3/printing/printfsp.c index efb97be919..6a8e4bea45 100644 --- a/source3/printing/printfsp.c +++ b/source3/printing/printfsp.c @@ -34,7 +34,7 @@ files_struct *print_fsp_open(connection_struct *conn,char *jobname) int jobid; SMB_STRUCT_STAT sbuf; extern struct current_user current_user; - files_struct *fsp = file_new(); + files_struct *fsp = file_new(conn); if(!fsp) return NULL; diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 45df9b2e0d..217c81228f 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -111,7 +111,7 @@ static int close_filestruct(files_struct *fsp) } /**************************************************************************** - Close a file - possibly invalidating the read prediction. + Close a file. If normal_close is 1 then this came from a normal SMBclose (or equivalent) operation otherwise it came as the result of some other operation such as diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 8b2c482b0a..9ec1fa2606 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -184,7 +184,6 @@ chmod a file - but preserve some bits ********************************************************************/ int file_chmod(connection_struct *conn,char *fname,int dosmode,SMB_STRUCT_STAT *st) { - extern struct current_user current_user; SMB_STRUCT_STAT st1; int mask=0; mode_t tmp; @@ -250,16 +249,21 @@ int file_chmod(connection_struct *conn,char *fname,int dosmode,SMB_STRUCT_STAT * /* Check if we have write access. */ if (CAN_WRITE(conn)) { - if (((st->st_mode & S_IWOTH) || - conn->admin_user || - ((st->st_mode & S_IWUSR) && current_user.uid==st->st_uid) || - ((st->st_mode & S_IWGRP) && - in_group(st->st_gid,current_user.gid, current_user.ngroups,current_user.groups)))) { - /* We are allowed to become root and change the file mode. */ - become_root(); - ret = vfs_chmod(conn,fname,unixmode); - unbecome_root(); - } + /* + * We need to open the file with write access whilst + * still in our current user context. This ensures we + * are not violating security in doing the fchmod. + * This file open does *not* break any oplocks we are + * holding. We need to review this.... may need to + * break batch oplocks open by others. JRA. + */ + files_struct *fsp = open_file_fchmod(conn,fname,st); + if (!fsp) + return -1; + become_root(); + ret = conn->vfs_ops.fchmod(fsp, fsp->fd, unixmode); + unbecome_root(); + close_file_fchmod(fsp); } return( ret ); diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 33243e1e94..27dfad7c48 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -43,7 +43,7 @@ static int files_used; /**************************************************************************** find first available file slot ****************************************************************************/ -files_struct *file_new(void ) +files_struct *file_new(connection_struct *conn) { int i; static int first_file; @@ -72,7 +72,7 @@ files_struct *file_new(void ) for (fsp=Files;fsp;fsp=next) { next=fsp->next; if (attempt_close_oplocked_file(fsp)) { - return file_new(); + return file_new(conn); } } @@ -91,6 +91,7 @@ files_struct *file_new(void ) ZERO_STRUCTP(fsp); fsp->fd = -1; + fsp->conn = conn; first_file = (i+1) % real_max_open_files; diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 007a169f9e..f450e74e58 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -583,13 +583,10 @@ files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_S return print_fsp_open(conn, fname); } - fsp = file_new(); + fsp = file_new(conn); if(!fsp) return NULL; - fsp->fd = -1; - fsp->conn = conn; /* The vfs_fXXX() macros need this. */ - DEBUG(10,("open_file_shared: fname = %s, share_mode = %x, ofun = %x, mode = %o, oplock request = %d\n", fname, share_mode, ofun, (int)mode, oplock_request )); @@ -870,7 +867,7 @@ files_struct *open_file_stat(connection_struct *conn, char *fname, return NULL; } - fsp = file_new(); + fsp = file_new(conn); if(!fsp) return NULL; @@ -919,6 +916,49 @@ files_struct *open_file_stat(connection_struct *conn, char *fname, } /**************************************************************************** + Open a file for for write to ensure that we can fchmod it. +****************************************************************************/ + +files_struct *open_file_fchmod(connection_struct *conn, char *fname, SMB_STRUCT_STAT *psbuf) +{ + files_struct *fsp = NULL; + BOOL fsp_open; + + if (!VALID_STAT(*psbuf)) + return NULL; + + fsp = file_new(conn); + if(!fsp) + return NULL; + + fsp_open = open_file(fsp,conn,fname,psbuf,O_WRONLY,0); + + /* + * This is not a user visible file open. + * Don't set a share mode and don't increment + * the conn->num_files_open. + */ + + if (!fsp_open) { + file_free(fsp); + return NULL; + } + + return fsp; +} + +/**************************************************************************** + Close the fchmod file fd - ensure no locks are lost. +****************************************************************************/ + +int close_file_fchmod(files_struct *fsp) +{ + int ret = fd_close(fsp->conn, fsp); + file_free(fsp); + return ret; +} + +/**************************************************************************** Open a directory from an NT SMB call. ****************************************************************************/ @@ -927,12 +967,12 @@ files_struct *open_directory(connection_struct *conn, char *fname, { extern struct current_user current_user; BOOL got_stat = False; - files_struct *fsp = file_new(); + files_struct *fsp = file_new(conn); if(!fsp) return NULL; - fsp->conn = conn; /* THe vfs_fXXX() macros need this. */ + fsp->conn = conn; /* The vfs_fXXX() macros need this. */ if (VALID_STAT(*psbuf)) got_stat = True; diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index a4057eb7ce..da8484e14e 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -369,6 +369,34 @@ int vfswrap_chmod(connection_struct *conn, char *path, mode_t mode) return result; } +int vfswrap_fchmod(files_struct *fsp, int fd, mode_t mode) +{ + int result; + struct vfs_ops *vfs_ops = &fsp->conn->vfs_ops; + + START_PROFILE(syscall_fchmod); + + /* + * We need to do this due to the fact that the default POSIX ACL + * chmod modifies the ACL *mask* for the group owner, not the + * group owner bits directly. JRA. + */ + + if (vfs_ops->fchmod_acl != NULL) { + int saved_errno = errno; /* We might get ENOSYS */ + if ((result = vfs_ops->fchmod_acl(fsp, fd, mode)) == 0) { + END_PROFILE(syscall_chmod); + return result; + } + /* Error - return the old errno. */ + errno = saved_errno; + } + + result = fchmod(fd, mode); + END_PROFILE(syscall_fchmod); + return result; +} + int vfswrap_chown(connection_struct *conn, char *path, uid_t uid, gid_t gid) { int result; @@ -386,6 +414,17 @@ int vfswrap_chown(connection_struct *conn, char *path, uid_t uid, gid_t gid) return result; } +int vfswrap_fchown(files_struct *fsp, int fd, uid_t uid, gid_t gid) +{ + int result; + + START_PROFILE(syscall_fchown); + + result = fchown(fd, uid, gid); + END_PROFILE(syscall_fchown); + return result; +} + int vfswrap_chdir(connection_struct *conn, char *path) { int result; @@ -452,7 +491,7 @@ int vfswrap_ftruncate(files_struct *fsp, int fd, SMB_OFF_T len) extend a file with ftruncate. Provide alternate implementation for this */ - struct vfs_ops *vfs_ops = fsp->conn->vfs_ops; + struct vfs_ops *vfs_ops = &fsp->conn->vfs_ops; SMB_STRUCT_STAT st; char c = 0; SMB_OFF_T currpos; diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index f5bd057ca6..713d58cdc8 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -64,7 +64,9 @@ struct vfs_ops default_vfs_ops = { vfswrap_lstat, vfswrap_unlink, vfswrap_chmod, + vfswrap_fchmod, vfswrap_chown, + vfswrap_fchown, vfswrap_chdir, vfswrap_getwd, vfswrap_utime, @@ -224,10 +226,18 @@ BOOL vfs_init_custom(connection_struct *conn) conn->vfs_ops.chmod = default_vfs_ops.chmod; } + if (conn->vfs_ops.fchmod == NULL) { + conn->vfs_ops.fchmod = default_vfs_ops.fchmod; + } + if (conn->vfs_ops.chown == NULL) { conn->vfs_ops.chown = default_vfs_ops.chown; } + if (conn->vfs_ops.fchown == NULL) { + conn->vfs_ops.fchown = default_vfs_ops.fchown; + } + if (conn->vfs_ops.chdir == NULL) { conn->vfs_ops.chdir = default_vfs_ops.chdir; } |