Google
  Web www.spinics.net

[PATCH 11/17] setpwnam: use xmkstemp() and lckpwdf()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]


Get rid private locking schema and use libc instead.

Signed-off-by: Sami Kerola <kerolasa@xxxxxx>
---
 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 47274bf..7bd2ddb 100644
--- a/login-utils/Makefile.am
+++ b/login-utils/Makefile.am
@@ -42,7 +42,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 0e0c047..97fd822 100644
--- a/login-utils/setpwnam.c
+++ b/login-utils/setpwnam.c
@@ -47,6 +47,7 @@
 #include <fcntl.h>
 #include <paths.h>
 #include <pwd.h>
+#include <shadow.h>
 #include <signal.h>
 #include <stdbool.h>
 #include <stdio.h>
@@ -58,6 +59,7 @@
 #include <unistd.h>
 
 #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;
@@ -164,8 +145,6 @@ int setpwnam(struct passwd *pwd)
 	if (rc < 0)
 		goto fail;
 
-	close(fd);
-	fd = -1;
 	fclose(pwf);	/* I don't think I want to know if this failed */
 	pwf = NULL;
 
@@ -178,22 +157,27 @@ int setpwnam(struct passwd *pwd)
 	unlink(PASSWD_FILE ".OLD");
 	/* we don't care if we can't create the backup file */
 	ignore_result(link(PASSWD_FILE, PASSWD_FILE ".OLD"));
+	/* xmkstemp is too restrictive by default for passwd file */
+	if (fchmod(fileno(fp), 0644) < 0)
+		goto fail;
 	/* 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;
 }
-- 
1.7.9.2

--
To unsubscribe from this list: send the line "unsubscribe util-linux" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Site Home]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Memory]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Rubini]     [Photo]     [Yosemite]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]     [Video 4 Linux]     [Linux Resources]

Powered by Linux