diff options
-rw-r--r-- | guts/lckpwdf.c | 32 | ||||
-rw-r--r-- | guts/ulckpwdf.c | 16 | ||||
-rw-r--r-- | pseudo.h | 4 | ||||
-rw-r--r-- | pseudo_client.c | 42 | ||||
-rw-r--r-- | pseudo_client.h | 10 | ||||
-rw-r--r-- | pseudo_util.c | 11 | ||||
-rw-r--r-- | wrapfuncs.in | 2 |
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; + * } + */ @@ -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); |