The file mode is passed from client to server as a printf string
formatted with %04o (unsigned) so use strtoul() not strtol() to
parse it. Error out on modes > 07777.
There is no way that the mode can ever be -1 so remove those checks.
This rabbit hole brought to you by:
usr.bin/rdistd/server.c:994: warning: comparison between signed and unsigned
- todd
Index: rdist/client.c
===================================================================
RCS file: /cvs/src/usr.bin/rdist/client.c,v
retrieving revision 1.35
diff -u -p -r1.35 client.c
--- rdist/client.c 9 Dec 2015 19:39:10 -0000 1.35
+++ rdist/client.c 30 Mar 2016 20:52:16 -0000
@@ -772,8 +772,8 @@ update(char *rname, opt_t opts, struct s
{
off_t size;
time_t mtime;
- unsigned short lmode;
- unsigned short rmode;
+ mode_t lmode;
+ mode_t rmode;
char *owner = NULL, *group = NULL;
int done, n;
u_char *cp;
@@ -1042,7 +1042,7 @@ statupdate(int u, char *starget, opt_t o
{
int rv = 0;
char ername[PATH_MAX*4];
- int lmode = st->st_mode & 07777;
+ mode_t lmode = st->st_mode & 07777;
if (u == US_CHMOG) {
if (IS_ON(opts, DO_VERIFY)) {
Index: rdistd/server.c
===================================================================
RCS file: /cvs/src/usr.bin/rdistd/server.c,v
retrieving revision 1.42
diff -u -p -r1.42 server.c
--- rdistd/server.c 30 Mar 2016 20:51:59 -0000 1.42
+++ rdistd/server.c 30 Mar 2016 20:52:16 -0000
@@ -60,8 +60,8 @@ int oumask; /* Old umask */
static int cattarget(char *);
static int setownership(char *, int, uid_t, gid_t, int);
-static int setfilemode(char *, int, int, int);
-static int fchog(int, char *, char *, char *, int);
+static int setfilemode(char *, int, mode_t, int);
+static int fchog(int, char *, char *, char *, mode_t);
static int removefile(struct stat *, int);
static void doclean(char *);
static void clean(char *);
@@ -70,9 +70,9 @@ static void docmdspecial(void);
static void query(char *);
static int chkparent(char *, opt_t);
static char *savetarget(char *, opt_t);
-static void recvfile(char *, opt_t, int, char *, char *, time_t, time_t,
off_t);
-static void recvdir(opt_t, int, char *, char *);
-static void recvlink(char *, opt_t, int, off_t);
+static void recvfile(char *, opt_t, mode_t, char *, char *, time_t, time_t,
off_t);
+static void recvdir(opt_t, mode_t, char *, char *);
+static void recvlink(char *, opt_t, mode_t, off_t);
static void hardlink(char *);
static void setconfig(char *);
static void recvit(char *, int);
@@ -148,13 +148,10 @@ setownership(char *file, int fd, uid_t u
* Set mode of a file
*/
static int
-setfilemode(char *file, int fd, int mode, int islink)
+setfilemode(char *file, int fd, mode_t mode, int islink)
{
int status = -1;
- if (mode == -1)
- return(0);
-
if (islink)
status = fchmodat(AT_FDCWD, file, mode, AT_SYMLINK_NOFOLLOW);
@@ -175,7 +172,7 @@ setfilemode(char *file, int fd, int mode
* Change owner, group and mode of file.
*/
static int
-fchog(int fd, char *file, char *owner, char *group, int mode)
+fchog(int fd, char *file, char *owner, char *group, mode_t mode)
{
static struct group *gr = NULL;
int i;
@@ -190,7 +187,7 @@ fchog(int fd, char *file, char *owner, c
uid = (uid_t) atoi(owner + 1);
} else if (pw == NULL || strcmp(owner, pw->pw_name) != 0) {
if ((pw = getpwnam(owner)) == NULL) {
- if (mode != -1 && IS_ON(mode, S_ISUID)) {
+ if (IS_ON(mode, S_ISUID)) {
message(MT_NOTICE,
"%s: unknown login name \"%s\", clearing setuid",
target, owner);
@@ -213,13 +210,10 @@ fchog(int fd, char *file, char *owner, c
} else { /* not root, setuid only if user==owner */
struct passwd *lupw;
- if (mode != -1) {
- if (IS_ON(mode, S_ISUID) &&
- strcmp(locuser, owner) != 0)
- mode &= ~S_ISUID;
- if (mode)
- mode &= ~S_ISVTX; /* and strip sticky too */
- }
+ if (IS_ON(mode, S_ISUID) && strcmp(locuser, owner) != 0)
+ mode &= ~S_ISUID;
+ if (mode)
+ mode &= ~S_ISVTX; /* and strip sticky too */
if ((lupw = getpwnam(locuser)) != NULL)
primegid = lupw->pw_gid;
@@ -230,7 +224,7 @@ fchog(int fd, char *file, char *owner, c
if ((*group == ':' &&
(getgrgid(gid = atoi(group + 1)) == NULL))
|| ((gr = (struct group *)getgrnam(group)) == NULL)) {
- if (mode != -1 && IS_ON(mode, S_ISGID)) {
+ if (IS_ON(mode, S_ISGID)) {
message(MT_NOTICE,
"%s: unknown group \"%s\", clearing setgid",
target, group);
@@ -249,7 +243,7 @@ fchog(int fd, char *file, char *owner, c
for (i = 0; gr->gr_mem[i] != NULL; i++)
if (strcmp(locuser, gr->gr_mem[i]) == 0)
goto ok;
- if (mode != -1 && IS_ON(mode, S_ISGID)) {
+ if (IS_ON(mode, S_ISGID)) {
message(MT_NOTICE,
"%s: user %s not in group %s, clearing setgid",
target, locuser, group);
@@ -268,12 +262,12 @@ ok:
* or otherwise, set the new file mode.
*/
if (setownership(file, fd, uid, gid, S_ISLNK(st.st_mode)) < 0) {
- if (mode != -1 && IS_ON(mode, S_ISUID)) {
+ if (IS_ON(mode, S_ISUID)) {
message(MT_NOTICE,
"%s: chown failed, clearing setuid", target);
mode &= ~S_ISUID;
}
- if (mode != -1 && IS_ON(mode, S_ISGID)) {
+ if (IS_ON(mode, S_ISGID)) {
message(MT_NOTICE,
"%s: chown failed, clearing setgid", target);
mode &= ~S_ISGID;
@@ -738,7 +732,7 @@ savetarget(char *file, opt_t opts)
* Receive a file
*/
static void
-recvfile(char *new, opt_t opts, int mode, char *owner, char *group,
+recvfile(char *new, opt_t opts, mode_t mode, char *owner, char *group,
time_t mtime, time_t atime, off_t size)
{
int f, wrerr, olderrno;
@@ -961,7 +955,7 @@ recvfile(char *new, opt_t opts, int mode
* Receive a directory
*/
static void
-recvdir(opt_t opts, int mode, char *owner, char *group)
+recvdir(opt_t opts, mode_t mode, char *owner, char *group)
{
static char lowner[100], lgroup[100];
char *cp;
@@ -1110,7 +1104,7 @@ recvdir(opt_t opts, int mode, char *owne
* Receive a link
*/
static void
-recvlink(char *new, opt_t opts, int mode, off_t size)
+recvlink(char *new, opt_t opts, mode_t mode, off_t size)
{
char tbuf[PATH_MAX], dbuf[BUFSIZ];
struct stat stb;
@@ -1256,9 +1250,7 @@ hardlink(char *cmd)
}
if (lstat(target, &stb) == 0) {
- int mode = stb.st_mode & S_IFMT;
-
- if (mode != S_IFREG && mode != S_IFLNK) {
+ if (!S_ISREG(stb.st_mode) && !S_ISLNK(stb.st_mode)) {
error("%s: not a regular file", target);
return;
}
@@ -1349,7 +1341,7 @@ setconfig(char *cmd)
static void
recvit(char *cmd, int type)
{
- int mode;
+ mode_t mode;
opt_t opts;
off_t size;
time_t mtime, atime;
@@ -1357,6 +1349,7 @@ recvit(char *cmd, int type)
char new[PATH_MAX];
char fileb[PATH_MAX];
int64_t freespace = -1, freefiles = -1;
+ unsigned long ulval;
char *cp = cmd;
/*
@@ -1371,11 +1364,16 @@ recvit(char *cmd, int type)
/*
* Get file mode
*/
- mode = strtol(cp, &cp, 8);
+ ulval = strtoul(cp, &cp, 8);
if (*cp++ != ' ') {
error("recvit: mode not delimited");
return;
}
+ if (ulval > 07777) {
+ error("recvit: invalid mode");
+ return;
+ }
+ mode = (mode_t)ulval;
/*
* Get file size
@@ -1536,11 +1534,12 @@ recvit(char *cmd, int type)
static void
dochmog(char *cmd)
{
- int mode;
+ mode_t mode;
opt_t opts;
char *owner, *group, *file;
char *cp = cmd;
char fileb[PATH_MAX];
+ unsigned long ulval;
/*
* Get rdist option flags
@@ -1554,11 +1553,16 @@ dochmog(char *cmd)
/*
* Get file mode
*/
- mode = strtol(cp, &cp, 8);
+ ulval = strtol(cp, &cp, 8);
if (*cp++ != ' ') {
error("dochmog: mode not delimited");
return;
}
+ if (ulval > 07777) {
+ error("dochmog: invalid mode");
+ return;
+ }
+ mode = (mode_t)ulval;
/*
* Get file owner name