[PATCH] uml: preserve errno in error paths

The poster child for this patch is the third tuntap_user hunk.  When an ioctl
fails, it properly closes the opened file descriptor and returns.  However,
the close resets errno to 0, and the 'return errno' that follows returns 0
rather than the value that ioctl set.  This caused the caller to believe that
the device open succeeded and had opened file descriptor 0, which caused no
end of interesting behavior.

The rest of this patch is a pass through the UML sources looking for places
where errno could be reset before being passed back out.  A common culprit is
printk, which could call write, being called before errno is returned.

In some cases, where the code ends up being much smaller, I just deleted the
printk.

There was another case where a caller of run_helper looked at errno after a
failure, rather than the return value of run_helper, which was the errno value
that it wanted.

Signed-off-by: Jeff Dike <jdike@addtoit.com>
Cc: Paolo Giarrusso <blaisorblade@yahoo.it>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
Jeff Dike 2005-09-16 19:27:49 -07:00 committed by Linus Torvalds
parent 64b7673f91
commit b4fd310e16
9 changed files with 67 additions and 78 deletions

View File

@ -54,7 +54,7 @@ static int mcast_open(void *data)
struct mcast_data *pri = data; struct mcast_data *pri = data;
struct sockaddr_in *sin = pri->mcast_addr; struct sockaddr_in *sin = pri->mcast_addr;
struct ip_mreq mreq; struct ip_mreq mreq;
int fd = -EINVAL, yes = 1, err = -EINVAL;; int fd, yes = 1, err = 0;
if ((sin->sin_addr.s_addr == 0) || (sin->sin_port == 0)) if ((sin->sin_addr.s_addr == 0) || (sin->sin_port == 0))
@ -65,13 +65,14 @@ static int mcast_open(void *data)
if (fd < 0){ if (fd < 0){
printk("mcast_open : data socket failed, errno = %d\n", printk("mcast_open : data socket failed, errno = %d\n",
errno); errno);
fd = -errno; err = -errno;
goto out; goto out;
} }
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) { if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) {
printk("mcast_open: SO_REUSEADDR failed, errno = %d\n", printk("mcast_open: SO_REUSEADDR failed, errno = %d\n",
errno); errno);
err = -errno;
goto out_close; goto out_close;
} }
@ -80,6 +81,7 @@ static int mcast_open(void *data)
sizeof(pri->ttl)) < 0) { sizeof(pri->ttl)) < 0) {
printk("mcast_open: IP_MULTICAST_TTL failed, error = %d\n", printk("mcast_open: IP_MULTICAST_TTL failed, error = %d\n",
errno); errno);
err = -errno;
goto out_close; goto out_close;
} }
@ -87,12 +89,14 @@ static int mcast_open(void *data)
if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &yes, sizeof(yes)) < 0) { if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &yes, sizeof(yes)) < 0) {
printk("mcast_open: IP_MULTICAST_LOOP failed, error = %d\n", printk("mcast_open: IP_MULTICAST_LOOP failed, error = %d\n",
errno); errno);
err = -errno;
goto out_close; goto out_close;
} }
/* bind socket to mcast address */ /* bind socket to mcast address */
if (bind(fd, (struct sockaddr *) sin, sizeof(*sin)) < 0) { if (bind(fd, (struct sockaddr *) sin, sizeof(*sin)) < 0) {
printk("mcast_open : data bind failed, errno = %d\n", errno); printk("mcast_open : data bind failed, errno = %d\n", errno);
err = -errno;
goto out_close; goto out_close;
} }
@ -107,14 +111,15 @@ static int mcast_open(void *data)
"interface on the host.\n"); "interface on the host.\n");
printk("eth0 should be configured in order to use the " printk("eth0 should be configured in order to use the "
"multicast transport.\n"); "multicast transport.\n");
err = -errno;
goto out_close; goto out_close;
} }
out:
return fd; return fd;
out_close: out_close:
os_close_file(fd); os_close_file(fd);
out:
return err; return err;
} }

View File

@ -173,9 +173,9 @@ int mconsole_notify(char *sock_name, int type, const void *data, int len)
if(notify_sock < 0){ if(notify_sock < 0){
notify_sock = socket(PF_UNIX, SOCK_DGRAM, 0); notify_sock = socket(PF_UNIX, SOCK_DGRAM, 0);
if(notify_sock < 0){ if(notify_sock < 0){
printk("mconsole_notify - socket failed, errno = %d\n",
errno);
err = -errno; err = -errno;
printk("mconsole_notify - socket failed, errno = %d\n",
err);
} }
} }
unlock_notify(); unlock_notify();
@ -198,8 +198,8 @@ int mconsole_notify(char *sock_name, int type, const void *data, int len)
n = sendto(notify_sock, &packet, len, 0, (struct sockaddr *) &target, n = sendto(notify_sock, &packet, len, 0, (struct sockaddr *) &target,
sizeof(target)); sizeof(target));
if(n < 0){ if(n < 0){
printk("mconsole_notify - sendto failed, errno = %d\n", errno);
err = -errno; err = -errno;
printk("mconsole_notify - sendto failed, errno = %d\n", errno);
} }
return(err); return(err);
} }

View File

@ -43,8 +43,9 @@ static int pts_open(int input, int output, int primary, void *d,
fd = get_pty(); fd = get_pty();
if(fd < 0){ if(fd < 0){
err = -errno;
printk("open_pts : Failed to open pts\n"); printk("open_pts : Failed to open pts\n");
return(-errno); return err;
} }
if(data->raw){ if(data->raw){
CATCH_EINTR(err = tcgetattr(fd, &data->tt)); CATCH_EINTR(err = tcgetattr(fd, &data->tt));

View File

@ -110,13 +110,15 @@ int xterm_open(int input, int output, int primary, void *d,
fd = mkstemp(file); fd = mkstemp(file);
if(fd < 0){ if(fd < 0){
err = -errno;
printk("xterm_open : mkstemp failed, errno = %d\n", errno); printk("xterm_open : mkstemp failed, errno = %d\n", errno);
return(-errno); return err;
} }
if(unlink(file)){ if(unlink(file)){
err = -errno;
printk("xterm_open : unlink failed, errno = %d\n", errno); printk("xterm_open : unlink failed, errno = %d\n", errno);
return(-errno); return err;
} }
os_close_file(fd); os_close_file(fd);

View File

@ -85,8 +85,8 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
data.fd = fds[1]; data.fd = fds[1];
pid = clone(helper_child, (void *) sp, CLONE_VM | SIGCHLD, &data); pid = clone(helper_child, (void *) sp, CLONE_VM | SIGCHLD, &data);
if(pid < 0){ if(pid < 0){
printk("run_helper : clone failed, errno = %d\n", errno);
ret = -errno; ret = -errno;
printk("run_helper : clone failed, errno = %d\n", errno);
goto out_close; goto out_close;
} }
@ -122,7 +122,7 @@ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags,
unsigned long *stack_out, int stack_order) unsigned long *stack_out, int stack_order)
{ {
unsigned long stack, sp; unsigned long stack, sp;
int pid, status; int pid, status, err;
stack = alloc_stack(stack_order, um_in_interrupt()); stack = alloc_stack(stack_order, um_in_interrupt());
if(stack == 0) return(-ENOMEM); if(stack == 0) return(-ENOMEM);
@ -130,16 +130,18 @@ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags,
sp = stack + (page_size() << stack_order) - sizeof(void *); sp = stack + (page_size() << stack_order) - sizeof(void *);
pid = clone(proc, (void *) sp, flags | SIGCHLD, arg); pid = clone(proc, (void *) sp, flags | SIGCHLD, arg);
if(pid < 0){ if(pid < 0){
err = -errno;
printk("run_helper_thread : clone failed, errno = %d\n", printk("run_helper_thread : clone failed, errno = %d\n",
errno); errno);
return(-errno); return err;
} }
if(stack_out == NULL){ if(stack_out == NULL){
CATCH_EINTR(pid = waitpid(pid, &status, 0)); CATCH_EINTR(pid = waitpid(pid, &status, 0));
if(pid < 0){ if(pid < 0){
err = -errno;
printk("run_helper_thread - wait failed, errno = %d\n", printk("run_helper_thread - wait failed, errno = %d\n",
errno); errno);
pid = -errno; pid = err;
} }
if(!WIFEXITED(status) || (WEXITSTATUS(status) != 0)) if(!WIFEXITED(status) || (WEXITSTATUS(status) != 0))
printk("run_helper_thread - thread returned status " printk("run_helper_thread - thread returned status "
@ -156,8 +158,8 @@ int helper_wait(int pid)
CATCH_EINTR(ret = waitpid(pid, NULL, WNOHANG)); CATCH_EINTR(ret = waitpid(pid, NULL, WNOHANG));
if(ret < 0){ if(ret < 0){
ret = -errno;
printk("helper_wait : waitpid failed, errno = %d\n", errno); printk("helper_wait : waitpid failed, errno = %d\n", errno);
return(-errno);
} }
return(ret); return(ret);
} }

View File

@ -109,18 +109,14 @@ int raw(int fd)
int err; int err;
CATCH_EINTR(err = tcgetattr(fd, &tt)); CATCH_EINTR(err = tcgetattr(fd, &tt));
if (err < 0) { if(err < 0)
printk("tcgetattr failed, errno = %d\n", errno); return -errno;
return(-errno);
}
cfmakeraw(&tt); cfmakeraw(&tt);
CATCH_EINTR(err = tcsetattr(fd, TCSADRAIN, &tt)); CATCH_EINTR(err = tcsetattr(fd, TCSADRAIN, &tt));
if (err < 0) { if(err < 0)
printk("tcsetattr failed, errno = %d\n", errno); return -errno;
return(-errno);
}
/* XXX tcsetattr could have applied only some changes /* XXX tcsetattr could have applied only some changes
* (and cfmakeraw() is a set of changes) */ * (and cfmakeraw() is a set of changes) */

View File

@ -313,15 +313,16 @@ static int init_aio_26(void)
int err; int err;
if(io_setup(256, &ctx)){ if(io_setup(256, &ctx)){
err = -errno;
printk("aio_thread failed to initialize context, err = %d\n", printk("aio_thread failed to initialize context, err = %d\n",
errno); errno);
return -errno; return err;
} }
err = run_helper_thread(aio_thread, NULL, err = run_helper_thread(aio_thread, NULL,
CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0); CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0);
if(err < 0) if(err < 0)
return -errno; return err;
aio_pid = err; aio_pid = err;

View File

@ -75,7 +75,7 @@ static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote,
struct msghdr msg; struct msghdr msg;
struct cmsghdr *cmsg; struct cmsghdr *cmsg;
struct iovec iov; struct iovec iov;
int pid, n; int pid, n, err;
sprintf(version_buf, "%d", UML_NET_VERSION); sprintf(version_buf, "%d", UML_NET_VERSION);
@ -105,9 +105,10 @@ static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote,
n = recvmsg(me, &msg, 0); n = recvmsg(me, &msg, 0);
*used_out = n; *used_out = n;
if(n < 0){ if(n < 0){
err = -errno;
printk("tuntap_open_tramp : recvmsg failed - errno = %d\n", printk("tuntap_open_tramp : recvmsg failed - errno = %d\n",
errno); errno);
return(-errno); return err;
} }
CATCH_EINTR(waitpid(pid, NULL, 0)); CATCH_EINTR(waitpid(pid, NULL, 0));
@ -147,9 +148,10 @@ static int tuntap_open(void *data)
ifr.ifr_flags = IFF_TAP | IFF_NO_PI; ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
strlcpy(ifr.ifr_name, pri->dev_name, sizeof(ifr.ifr_name)); strlcpy(ifr.ifr_name, pri->dev_name, sizeof(ifr.ifr_name));
if(ioctl(pri->fd, TUNSETIFF, (void *) &ifr) < 0){ if(ioctl(pri->fd, TUNSETIFF, (void *) &ifr) < 0){
err = -errno;
printk("TUNSETIFF failed, errno = %d\n", errno); printk("TUNSETIFF failed, errno = %d\n", errno);
os_close_file(pri->fd); os_close_file(pri->fd);
return(-errno); return err;
} }
} }
else { else {

View File

@ -119,15 +119,11 @@ int os_window_size(int fd, int *rows, int *cols)
int os_new_tty_pgrp(int fd, int pid) int os_new_tty_pgrp(int fd, int pid)
{ {
if(ioctl(fd, TIOCSCTTY, 0) < 0){ if(ioctl(fd, TIOCSCTTY, 0) < 0)
printk("TIOCSCTTY failed, errno = %d\n", errno); return -errno;
return(-errno);
}
if(tcsetpgrp(fd, pid) < 0){ if(tcsetpgrp(fd, pid) < 0)
printk("tcsetpgrp failed, errno = %d\n", errno); return -errno;
return(-errno);
}
return(0); return(0);
} }
@ -146,18 +142,12 @@ int os_set_slip(int fd)
int disc, sencap; int disc, sencap;
disc = N_SLIP; disc = N_SLIP;
if(ioctl(fd, TIOCSETD, &disc) < 0){ if(ioctl(fd, TIOCSETD, &disc) < 0)
printk("Failed to set slip line discipline - " return -errno;
"errno = %d\n", errno);
return(-errno);
}
sencap = 0; sencap = 0;
if(ioctl(fd, SIOCSIFENCAP, &sencap) < 0){ if(ioctl(fd, SIOCSIFENCAP, &sencap) < 0)
printk("Failed to set slip encapsulation - " return -errno;
"errno = %d\n", errno);
return(-errno);
}
return(0); return(0);
} }
@ -180,22 +170,15 @@ int os_sigio_async(int master, int slave)
int flags; int flags;
flags = fcntl(master, F_GETFL); flags = fcntl(master, F_GETFL);
if(flags < 0) { if(flags < 0)
printk("fcntl F_GETFL failed, errno = %d\n", errno); return errno;
return(-errno);
}
if((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) || if((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) ||
(fcntl(master, F_SETOWN, os_getpid()) < 0)){ (fcntl(master, F_SETOWN, os_getpid()) < 0))
printk("fcntl F_SETFL or F_SETOWN failed, errno = %d\n", return -errno;
errno);
return(-errno);
}
if((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0)){ if((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0))
printk("fcntl F_SETFL failed, errno = %d\n", errno); return -errno;
return(-errno);
}
return(0); return(0);
} }
@ -255,7 +238,7 @@ int os_file_mode(char *file, struct openflags *mode_out)
int os_open_file(char *file, struct openflags flags, int mode) int os_open_file(char *file, struct openflags flags, int mode)
{ {
int fd, f = 0; int fd, err, f = 0;
if(flags.r && flags.w) f = O_RDWR; if(flags.r && flags.w) f = O_RDWR;
else if(flags.r) f = O_RDONLY; else if(flags.r) f = O_RDONLY;
@ -272,8 +255,9 @@ int os_open_file(char *file, struct openflags flags, int mode)
return(-errno); return(-errno);
if(flags.cl && fcntl(fd, F_SETFD, 1)){ if(flags.cl && fcntl(fd, F_SETFD, 1)){
err = -errno;
os_close_file(fd); os_close_file(fd);
return(-errno); return err;
} }
return(fd); return(fd);
@ -383,9 +367,9 @@ int os_file_size(char *file, unsigned long long *size_out)
return(fd); return(fd);
} }
if(ioctl(fd, BLKGETSIZE, &blocks) < 0){ if(ioctl(fd, BLKGETSIZE, &blocks) < 0){
err = -errno;
printk("Couldn't get the block size of \"%s\", " printk("Couldn't get the block size of \"%s\", "
"errno = %d\n", file, errno); "errno = %d\n", file, errno);
err = -errno;
os_close_file(fd); os_close_file(fd);
return(err); return(err);
} }
@ -473,11 +457,14 @@ int os_pipe(int *fds, int stream, int close_on_exec)
int os_set_fd_async(int fd, int owner) int os_set_fd_async(int fd, int owner)
{ {
int err;
/* XXX This should do F_GETFL first */ /* XXX This should do F_GETFL first */
if(fcntl(fd, F_SETFL, O_ASYNC | O_NONBLOCK) < 0){ if(fcntl(fd, F_SETFL, O_ASYNC | O_NONBLOCK) < 0){
err = -errno;
printk("os_set_fd_async : failed to set O_ASYNC and " printk("os_set_fd_async : failed to set O_ASYNC and "
"O_NONBLOCK on fd # %d, errno = %d\n", fd, errno); "O_NONBLOCK on fd # %d, errno = %d\n", fd, errno);
return(-errno); return err;
} }
#ifdef notdef #ifdef notdef
if(fcntl(fd, F_SETFD, 1) < 0){ if(fcntl(fd, F_SETFD, 1) < 0){
@ -488,10 +475,11 @@ int os_set_fd_async(int fd, int owner)
if((fcntl(fd, F_SETSIG, SIGIO) < 0) || if((fcntl(fd, F_SETSIG, SIGIO) < 0) ||
(fcntl(fd, F_SETOWN, owner) < 0)){ (fcntl(fd, F_SETOWN, owner) < 0)){
err = -errno;
printk("os_set_fd_async : Failed to fcntl F_SETOWN " printk("os_set_fd_async : Failed to fcntl F_SETOWN "
"(or F_SETSIG) fd %d to pid %d, errno = %d\n", fd, "(or F_SETSIG) fd %d to pid %d, errno = %d\n", fd,
owner, errno); owner, errno);
return(-errno); return err;
} }
return(0); return(0);
@ -516,11 +504,9 @@ int os_set_fd_block(int fd, int blocking)
if(blocking) flags &= ~O_NONBLOCK; if(blocking) flags &= ~O_NONBLOCK;
else flags |= O_NONBLOCK; else flags |= O_NONBLOCK;
if(fcntl(fd, F_SETFL, flags) < 0){ if(fcntl(fd, F_SETFL, flags) < 0)
printk("Failed to change blocking on fd # %d, errno = %d\n", return -errno;
fd, errno);
return(-errno);
}
return(0); return(0);
} }
@ -609,11 +595,8 @@ int os_create_unix_socket(char *file, int len, int close_on_exec)
int sock, err; int sock, err;
sock = socket(PF_UNIX, SOCK_DGRAM, 0); sock = socket(PF_UNIX, SOCK_DGRAM, 0);
if (sock < 0){ if(sock < 0)
printk("create_unix_socket - socket failed, errno = %d\n", return -errno;
errno);
return(-errno);
}
if(close_on_exec) { if(close_on_exec) {
err = os_set_exec_close(sock, 1); err = os_set_exec_close(sock, 1);
@ -628,11 +611,8 @@ int os_create_unix_socket(char *file, int len, int close_on_exec)
snprintf(addr.sun_path, len, "%s", file); snprintf(addr.sun_path, len, "%s", file);
err = bind(sock, (struct sockaddr *) &addr, sizeof(addr)); err = bind(sock, (struct sockaddr *) &addr, sizeof(addr));
if (err < 0){ if(err < 0)
printk("create_listening_socket at '%s' - bind failed, " return -errno;
"errno = %d\n", file, errno);
return(-errno);
}
return(sock); return(sock);
} }