[dovecot-cvs] dovecot/src/lib safe-mkdir.c,1.2,1.3
cras at procontrol.fi
cras at procontrol.fi
Thu Feb 27 00:19:53 EET 2003
Update of /home/cvs/dovecot/src/lib
In directory danu:/tmp/cvs-serv2547/lib
Modified Files:
safe-mkdir.c
Log Message:
safe_mkdir(): usage fchmod() and fchown(). chmod() wasn't really safe and
lchown() wasn't portable.
Index: safe-mkdir.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib/safe-mkdir.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- safe-mkdir.c 21 Dec 2002 12:35:34 -0000 1.2
+++ safe-mkdir.c 26 Feb 2003 22:19:51 -0000 1.3
@@ -26,11 +26,12 @@
#include <sys/stat.h>
#include <unistd.h>
+#include <fcntl.h>
int safe_mkdir(const char *dir, mode_t mode, uid_t uid, gid_t gid)
{
struct stat st;
- int ret = 1;
+ int fd, ret = 1;
if (lstat(dir, &st) < 0) {
if (errno != ENOENT)
@@ -38,37 +39,46 @@
if (mkdir(dir, mode) < 0)
i_fatal("Can't create directory %s: %m", dir);
-
- if (lchown(dir, uid, gid) < 0)
- i_fatal("lchown() failed for %s: %m", dir);
} else {
- /* make sure it's permissions are correct */
- if (!S_ISDIR(st.st_mode) || S_ISLNK(st.st_mode))
- i_fatal("Not a directory %s", dir);
+ /* already exists. */
+ ret = 2;
+ }
- if (st.st_uid != uid || st.st_gid != gid) {
- if (lchown(dir, uid, gid) < 0)
- i_fatal("lchown() failed for %s: %m", dir);
- ret = 0;
- }
+ /* use fchown() and fchmod() just to make sure we aren't following
+ symbolic links. */
+ fd = open(dir, O_RDONLY);
+ if (fd == -1)
+ i_fatal("open() failed for %s: %m", dir);
- if ((st.st_mode & 07777) != mode) {
- if (chmod(dir, mode) < 0)
- i_fatal("chmod() failed for %s: %m", dir);
- ret = 0;
- }
+ if (fstat(fd, &st) < 0)
+ i_fatal("fstat() failed for %s: %m", dir);
+
+ if (!S_ISDIR(st.st_mode) || S_ISLNK(st.st_mode))
+ i_fatal("Not a directory %s", dir);
+
+ if (st.st_uid != uid || st.st_gid != gid) {
+ if (fchown(fd, uid, gid) < 0)
+ i_fatal("fchown() failed for %s: %m", dir);
+ ret = 0;
+ }
+
+ if ((st.st_mode & 07777) != mode) {
+ if (fchmod(fd, mode) < 0)
+ i_fatal("chmod() failed for %s: %m", dir);
+ ret = 0;
}
+ if (close(fd) < 0)
+ i_fatal("close() failed for %s: %m", dir);
+
/* make sure we succeeded in everything. chown() and chmod()
are racy: user owned 0777 file - change either and the user
can still change it back. */
if (lstat(dir, &st) < 0)
i_fatal("lstat() check failed for %s: %m", dir);
- if (!S_ISDIR(st.st_mode) || S_ISLNK(st.st_mode)) {
- i_fatal("safe_mkdir() failed: %s is still not a directory",
- dir);
- }
+ if (!S_ISDIR(st.st_mode) || S_ISLNK(st.st_mode))
+ i_fatal("Not a directory %s", dir);
if ((st.st_mode & 07777) != mode) {
i_fatal("safe_mkdir() failed: %s (%o) is still not mode %o",
More information about the dovecot-cvs
mailing list