aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Seebach <seebs@eee12.(none)>2010-04-05 18:25:30 -0500
committerPeter Seebach <peter.seebach@windriver.com>2010-04-26 17:13:12 -0700
commitd686759bcfe87a08336470666283c4b2ab6ad510 (patch)
tree2b3361e223e8c7dffbde7a7ed6dbed0fc777da0a
parent9517843c85e733df325aabe24b0fb16cc1beaf94 (diff)
downloadpseudo-d686759bcfe87a08336470666283c4b2ab6ad510.tar.gz
pseudo-d686759bcfe87a08336470666283c4b2ab6ad510.tar.bz2
pseudo-d686759bcfe87a08336470666283c4b2ab6ad510.zip
Add lckpwdf()/ulckpwdf().
It's not enough to rely on the usual chroot() stuff affecting the file open, not least because these use the glibc-internal __open which is not currently intercepted, but also because we want to use the PSEUDO_PASSWD path when that's set but there's no chroot(). There's some extra magic in pseudo_etc_file to support these operations, since they can legitimately create a file rather than opening an existing one.
-rw-r--r--guts/lckpwdf.c32
-rw-r--r--guts/ulckpwdf.c16
-rw-r--r--pseudo.h4
-rw-r--r--pseudo_client.c42
-rw-r--r--pseudo_client.h10
-rw-r--r--pseudo_util.c11
-rw-r--r--wrapfuncs.in2
7 files changed, 103 insertions, 14 deletions
diff --git a/guts/lckpwdf.c b/guts/lckpwdf.c
new file mode 100644
index 0000000..b452ec0
--- /dev/null
+++ b/guts/lckpwdf.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_lckpwdf(void) {
+ * int rc = -1;
+ */
+ rc = pseudo_pwd_lck_open();
+ if (rc != -1) {
+ struct flock lck = {
+ .l_type = F_RDLCK,
+ .l_whence = SEEK_SET,
+ .l_start = 0,
+ .l_len = 1
+ };
+ /* I don't really care whether this works. */
+ fcntl(rc, F_SETFD, FD_CLOEXEC);
+ /* Now lock it. */
+ alarm(15); /* magic number from man page */
+ rc = fcntl(rc, F_SETLKW, &lck);
+ alarm(0);
+ if (rc == -1) {
+ int save_errno = errno;
+ pseudo_pwd_lck_close();
+ errno = save_errno;
+ }
+ }
+
+/* return rc;
+ * }
+ */
diff --git a/guts/ulckpwdf.c b/guts/ulckpwdf.c
new file mode 100644
index 0000000..bdb6f42
--- /dev/null
+++ b/guts/ulckpwdf.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_ulckpwdf(void) {
+ * int rc = -1;
+ */
+
+ /* lock is cleared automatically on close */
+ pseudo_pwd_lck_close();
+ rc = 0;
+
+/* return rc;
+ * }
+ */
diff --git a/pseudo.h b/pseudo.h
index 91b4dc7..85fd3d1 100644
--- a/pseudo.h
+++ b/pseudo.h
@@ -128,8 +128,8 @@ extern char *pseudo_get_prefix(char *);
extern ssize_t pseudo_sys_path_max(void);
extern ssize_t pseudo_path_max(void);
#define PSEUDO_PWD_MAX 4096
-extern int pseudo_etc_file(char *filename, char **search, int dircount);
-#define PSEUDO_ETC_FILE(name) pseudo_etc_file((name), (char *[]) { pseudo_chroot, pseudo_passwd }, 2)
+extern int pseudo_etc_file(const char *filename, char *realname, int flags, char **search, int dircount);
+#define PSEUDO_ETC_FILE(name, realname, flags) pseudo_etc_file((name), (realname), (flags), (char *[]) { pseudo_chroot, pseudo_passwd }, 2)
extern char *pseudo_version;
diff --git a/pseudo_client.c b/pseudo_client.c
index f009d8b..421fe61 100644
--- a/pseudo_client.c
+++ b/pseudo_client.c
@@ -43,6 +43,8 @@ static int connect_fd = -1;
static int server_pid = 0;
int pseudo_dir_fd = -1;
int pseudo_pwd_fd = -1;
+int pseudo_pwd_lck_fd = -1;
+char *pseudo_pwd_lck_name = NULL;
FILE *pseudo_pwd = NULL;
int pseudo_grp_fd = -1;
FILE *pseudo_grp = NULL;
@@ -97,7 +99,7 @@ pseudo_file_open(char *name, int *fd, FILE **fp) {
}
pseudo_file_close(fd, fp);
pseudo_antimagic();
- *fd = PSEUDO_ETC_FILE(name);
+ *fd = PSEUDO_ETC_FILE(name, NULL, O_RDONLY);
if (*fd >= 0) {
*fd = pseudo_fd(*fd, MOVE_FD);
*fp = fdopen(*fd, "r");
@@ -110,23 +112,53 @@ pseudo_file_open(char *name, int *fd, FILE **fp) {
return *fp;
}
+/* there is no spec I know of requiring us to defend this fd
+ * against being closed by the user.
+ */
+int
+pseudo_pwd_lck_open(void) {
+ if (!pseudo_pwd_lck_name) {
+ pseudo_pwd_lck_name = malloc(pseudo_path_max());
+ if (!pseudo_pwd_lck_name) {
+ pseudo_diag("couldn't allocate space for passwd lockfile path.\n");
+ return -1;
+ }
+ }
+ pseudo_pwd_lck_fd = PSEUDO_ETC_FILE(".pwd.lock",
+ pseudo_pwd_lck_name, O_RDWR | O_CREAT);
+ return pseudo_pwd_lck_fd;
+}
+
+void
+pseudo_pwd_lck_close(void) {
+ if (pseudo_pwd_lck_fd != -1) {
+ close(pseudo_pwd_lck_fd);
+ if (pseudo_pwd_lck_name) {
+ unlink(pseudo_pwd_lck_name);
+ free(pseudo_pwd_lck_name);
+ pseudo_pwd_lck_name = 0;
+ }
+ pseudo_pwd_lck_fd = -1;
+ }
+}
+
FILE *
-pseudo_pwd_open() {
+pseudo_pwd_open(void) {
return pseudo_file_open("passwd", &pseudo_pwd_fd, &pseudo_pwd);
}
void
-pseudo_pwd_close() {
+pseudo_pwd_close(void) {
pseudo_file_close(&pseudo_pwd_fd, &pseudo_pwd);
}
FILE *
-pseudo_grp_open() {
+pseudo_grp_open(void) {
return pseudo_file_open("group", &pseudo_grp_fd, &pseudo_grp);
}
void
-pseudo_grp_close() {
+pseudo_grp_close(void) {
pseudo_file_close(&pseudo_grp_fd, &pseudo_grp);
}
diff --git a/pseudo_client.h b/pseudo_client.h
index e2a36f6..b1c730c 100644
--- a/pseudo_client.h
+++ b/pseudo_client.h
@@ -40,10 +40,12 @@ extern gid_t pseudo_sgid;
extern gid_t pseudo_rgid;
extern gid_t pseudo_fgid;
extern int pseudo_dir_fd;
-extern FILE *pseudo_pwd_open();
-extern FILE *pseudo_grp_open();
-extern void pseudo_pwd_close();
-extern void pseudo_grp_close();
+extern FILE *pseudo_pwd_open(void);
+extern FILE *pseudo_grp_open(void);
+extern void pseudo_pwd_close(void);
+extern void pseudo_grp_close(void);
+extern int pseudo_pwd_lck_open(void);
+extern void pseudo_pwd_lck_close(void);
extern FILE *pseudo_pwd;
extern FILE *pseudo_grp;
diff --git a/pseudo_util.c b/pseudo_util.c
index 8b579f9..bef86ad 100644
--- a/pseudo_util.c
+++ b/pseudo_util.c
@@ -629,7 +629,7 @@ pseudo_access_fopen(const char *mode) {
*/
int
-pseudo_etc_file(char *file, char **search_dirs, int dircount) {
+pseudo_etc_file(const char *file, char *realname, int flags, char **search_dirs, int dircount) {
char filename[pseudo_path_max()];
int rc;
@@ -646,8 +646,10 @@ pseudo_etc_file(char *file, char **search_dirs, int dircount) {
continue;
snprintf(filename, pseudo_path_max(), "%s/etc/%s",
s, file);
- rc = open(filename, O_RDONLY);
+ rc = open(filename, flags);
if (rc >= 0) {
+ if (realname)
+ strcpy(realname, filename);
pseudo_debug(2, "using <%s> for <%s>\n",
filename, file);
return rc;
@@ -662,6 +664,9 @@ pseudo_etc_file(char *file, char **search_dirs, int dircount) {
snprintf(filename, pseudo_path_max(), "/etc/%s", file);
pseudo_debug(2, "falling back on <%s> for <%s>\n",
filename, file);
- return open(filename, O_RDONLY);
+ rc = open(filename, flags);
+ if (rc >= 0 && realname)
+ strcpy(realname, filename);
+ return rc;
}
diff --git a/wrapfuncs.in b/wrapfuncs.in
index 26ef1b7..c572ddf 100644
--- a/wrapfuncs.in
+++ b/wrapfuncs.in
@@ -98,6 +98,8 @@ int getpwent_r(struct passwd *pwbuf, char *buf, size_t buflen, struct passwd **p
struct passwd *getpwent(void);
void setpwent(void);
void endpwent(void);
+int lckpwdf(void);
+int ulckpwdf(void);
int getpw(uid_t uid, char *buf);
struct group *getgrnam(const char *name);
struct group *getgrgid(gid_t gid);