From decd963251a33c7cfbcc8870ab8cddf6b849d528 Mon Sep 17 00:00:00 2001 From: Sami Kerola Date: Wed, 29 Feb 2012 12:37:51 +0100 Subject: [PATCH] setpwnam: use xmkstemp() and lckpwdf() Get rid private locking schema and use libc instead. Signed-off-by: Sami Kerola --- login-utils/Makefile.am | 3 ++- login-utils/setpwnam.c | 52 ++++++++++++++--------------------------- 2 files changed, 20 insertions(+), 35 deletions(-) diff --git a/login-utils/Makefile.am b/login-utils/Makefile.am index 11f2b07d10..8328c66ab6 100644 --- a/login-utils/Makefile.am +++ b/login-utils/Makefile.am @@ -55,7 +55,8 @@ chfn_chsh_common = \ islocal.h \ setpwnam.c \ setpwnam.h \ - $(top_srcdir)/lib/env.c + $(top_srcdir)/lib/env.c \ + $(top_srcdir)/lib/fileutils.c login_SOURCES = \ login.c \ logindefs.c \ diff --git a/login-utils/setpwnam.c b/login-utils/setpwnam.c index 0e0c0478d4..6f3f4920a7 100644 --- a/login-utils/setpwnam.c +++ b/login-utils/setpwnam.c @@ -47,6 +47,7 @@ #include #include #include +#include #include #include #include @@ -58,6 +59,7 @@ #include #include "c.h" +#include "fileutils.h" #include "setpwnam.h" static void pw_init(void); @@ -71,47 +73,26 @@ static void pw_init(void); int setpwnam(struct passwd *pwd) { FILE *fp = NULL, *pwf = NULL; - int x, save_errno, fd, ret; + int save_errno; int found; - int oldumask; int namelen; int buflen = 256; int contlen, rc; char *linebuf = NULL; - - oldumask = umask(0); /* Create with exact permissions */ + char *tmpname = NULL; pw_init(); - /* sanity check */ - for (x = 0; x < 3; x++) { - if (x > 0) - sleep(1); - fd = open(PTMPTMP_FILE, O_WRONLY | O_CREAT | O_EXCL, 0644); - if (fd == -1) { - umask(oldumask); - return -1; - } - ret = link(PTMPTMP_FILE, PTMP_FILE); - unlink(PTMPTMP_FILE); - if (ret == -1) - close(fd); - else - break; - } - umask(oldumask); - if (ret == -1) + if ((fp = xmkstemp(&tmpname)) == NULL) return -1; /* ptmp should be owned by root.root or root.wheel */ - if (chown(PTMP_FILE, (uid_t) 0, (gid_t) 0) < 0) - return -1; - - /* open ptmp for writing and passwd for reading */ - fp = fdopen(fd, "w"); - if (!fp) + if (fchown(fileno(fp), (uid_t) 0, (gid_t) 0) < 0) goto fail; + /* acquire exclusive lock */ + if (lckpwdf() < 0) + goto fail; pwf = fopen(PASSWD_FILE, "r"); if (!pwf) goto fail; @@ -159,13 +140,14 @@ int setpwnam(struct passwd *pwd) fputs(linebuf, fp); } + /* xmkstemp is too restrictive by default for passwd file */ + if (fchmod(fileno(fp), 0644) < 0) + goto fail; rc = fclose(fp); fp = NULL; if (rc < 0) goto fail; - close(fd); - fd = -1; fclose(pwf); /* I don't think I want to know if this failed */ pwf = NULL; @@ -179,21 +161,23 @@ int setpwnam(struct passwd *pwd) /* we don't care if we can't create the backup file */ ignore_result(link(PASSWD_FILE, PASSWD_FILE ".OLD")); /* we DO care if we can't rename to the passwd file */ - if (rename(PTMP_FILE, PASSWD_FILE) < 0) + if (rename(tmpname, PASSWD_FILE) < 0) goto fail; /* finally: success */ + ulckpwdf(); return 0; fail: save_errno = errno; + ulckpwdf(); if (fp != NULL) fclose(fp); + if (tmpname != NULL) + unlink(tmpname); + free(tmpname); if (pwf != NULL) fclose(pwf); - if (fd >= 0) - close(fd); free(linebuf); - unlink(PTMP_FILE); errno = save_errno; return -1; } -- 2.47.2