diff options
author | Jeff Dike <jdike@addtoit.com> | 2005-09-17 02:27:49 (GMT) |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-09-17 18:50:00 (GMT) |
commit | b4fd310e163477236a241580b3b8c29aee65f4cc (patch) | |
tree | 3aec7527c4a9589824cb4d96f87446eb59bdef10 | |
parent | 64b7673f91c0c3614028c5942b0d6a91d0b64a98 (diff) | |
download | linux-b4fd310e163477236a241580b3b8c29aee65f4cc.tar.xz |
[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>
-rw-r--r-- | arch/um/drivers/mcast_user.c | 11 | ||||
-rw-r--r-- | arch/um/drivers/mconsole_user.c | 6 | ||||
-rw-r--r-- | arch/um/drivers/pty.c | 3 | ||||
-rw-r--r-- | arch/um/drivers/xterm.c | 6 | ||||
-rw-r--r-- | arch/um/kernel/helper.c | 12 | ||||
-rw-r--r-- | arch/um/kernel/user_util.c | 12 | ||||
-rw-r--r-- | arch/um/os-Linux/aio.c | 5 | ||||
-rw-r--r-- | arch/um/os-Linux/drivers/tuntap_user.c | 8 | ||||
-rw-r--r-- | arch/um/os-Linux/file.c | 82 |
9 files changed, 67 insertions, 78 deletions
diff --git a/arch/um/drivers/mcast_user.c b/arch/um/drivers/mcast_user.c index 3fd69067..5db136e 100644 --- a/arch/um/drivers/mcast_user.c +++ b/arch/um/drivers/mcast_user.c @@ -54,7 +54,7 @@ static int mcast_open(void *data) struct mcast_data *pri = data; struct sockaddr_in *sin = pri->mcast_addr; 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)) @@ -65,13 +65,14 @@ static int mcast_open(void *data) if (fd < 0){ printk("mcast_open : data socket failed, errno = %d\n", errno); - fd = -errno; + err = -errno; goto out; } if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) { printk("mcast_open: SO_REUSEADDR failed, errno = %d\n", errno); + err = -errno; goto out_close; } @@ -80,6 +81,7 @@ static int mcast_open(void *data) sizeof(pri->ttl)) < 0) { printk("mcast_open: IP_MULTICAST_TTL failed, error = %d\n", errno); + err = -errno; 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) { printk("mcast_open: IP_MULTICAST_LOOP failed, error = %d\n", errno); + err = -errno; goto out_close; } /* bind socket to mcast address */ if (bind(fd, (struct sockaddr *) sin, sizeof(*sin)) < 0) { printk("mcast_open : data bind failed, errno = %d\n", errno); + err = -errno; goto out_close; } @@ -107,14 +111,15 @@ static int mcast_open(void *data) "interface on the host.\n"); printk("eth0 should be configured in order to use the " "multicast transport.\n"); + err = -errno; goto out_close; } - out: return fd; out_close: os_close_file(fd); + out: return err; } diff --git a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c index a5b8aea..310c1f8 100644 --- a/arch/um/drivers/mconsole_user.c +++ b/arch/um/drivers/mconsole_user.c @@ -173,9 +173,9 @@ int mconsole_notify(char *sock_name, int type, const void *data, int len) if(notify_sock < 0){ notify_sock = socket(PF_UNIX, SOCK_DGRAM, 0); if(notify_sock < 0){ - printk("mconsole_notify - socket failed, errno = %d\n", - errno); err = -errno; + printk("mconsole_notify - socket failed, errno = %d\n", + err); } } 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, sizeof(target)); if(n < 0){ - printk("mconsole_notify - sendto failed, errno = %d\n", errno); err = -errno; + printk("mconsole_notify - sendto failed, errno = %d\n", errno); } return(err); } diff --git a/arch/um/drivers/pty.c b/arch/um/drivers/pty.c index ed84d01..0306a1b 100644 --- a/arch/um/drivers/pty.c +++ b/arch/um/drivers/pty.c @@ -43,8 +43,9 @@ static int pts_open(int input, int output, int primary, void *d, fd = get_pty(); if(fd < 0){ + err = -errno; printk("open_pts : Failed to open pts\n"); - return(-errno); + return err; } if(data->raw){ CATCH_EINTR(err = tcgetattr(fd, &data->tt)); diff --git a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c index 93dc191..90e0e5f 100644 --- a/arch/um/drivers/xterm.c +++ b/arch/um/drivers/xterm.c @@ -110,13 +110,15 @@ int xterm_open(int input, int output, int primary, void *d, fd = mkstemp(file); if(fd < 0){ + err = -errno; printk("xterm_open : mkstemp failed, errno = %d\n", errno); - return(-errno); + return err; } if(unlink(file)){ + err = -errno; printk("xterm_open : unlink failed, errno = %d\n", errno); - return(-errno); + return err; } os_close_file(fd); diff --git a/arch/um/kernel/helper.c b/arch/um/kernel/helper.c index f83e1e8..33fb0bd 100644 --- a/arch/um/kernel/helper.c +++ b/arch/um/kernel/helper.c @@ -85,8 +85,8 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv, data.fd = fds[1]; pid = clone(helper_child, (void *) sp, CLONE_VM | SIGCHLD, &data); if(pid < 0){ - printk("run_helper : clone failed, errno = %d\n", errno); ret = -errno; + printk("run_helper : clone failed, errno = %d\n", errno); 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, sp; - int pid, status; + int pid, status, err; stack = alloc_stack(stack_order, um_in_interrupt()); 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 *); pid = clone(proc, (void *) sp, flags | SIGCHLD, arg); if(pid < 0){ + err = -errno; printk("run_helper_thread : clone failed, errno = %d\n", errno); - return(-errno); + return err; } if(stack_out == NULL){ CATCH_EINTR(pid = waitpid(pid, &status, 0)); if(pid < 0){ + err = -errno; printk("run_helper_thread - wait failed, errno = %d\n", errno); - pid = -errno; + pid = err; } if(!WIFEXITED(status) || (WEXITSTATUS(status) != 0)) printk("run_helper_thread - thread returned status " @@ -156,8 +158,8 @@ int helper_wait(int pid) CATCH_EINTR(ret = waitpid(pid, NULL, WNOHANG)); if(ret < 0){ + ret = -errno; printk("helper_wait : waitpid failed, errno = %d\n", errno); - return(-errno); } return(ret); } diff --git a/arch/um/kernel/user_util.c b/arch/um/kernel/user_util.c index 954ff67..a25f3ea 100644 --- a/arch/um/kernel/user_util.c +++ b/arch/um/kernel/user_util.c @@ -109,18 +109,14 @@ int raw(int fd) int err; CATCH_EINTR(err = tcgetattr(fd, &tt)); - if (err < 0) { - printk("tcgetattr failed, errno = %d\n", errno); - return(-errno); - } + if(err < 0) + return -errno; cfmakeraw(&tt); CATCH_EINTR(err = tcsetattr(fd, TCSADRAIN, &tt)); - if (err < 0) { - printk("tcsetattr failed, errno = %d\n", errno); - return(-errno); - } + if(err < 0) + return -errno; /* XXX tcsetattr could have applied only some changes * (and cfmakeraw() is a set of changes) */ diff --git a/arch/um/os-Linux/aio.c b/arch/um/os-Linux/aio.c index 182905b..e942beb 100644 --- a/arch/um/os-Linux/aio.c +++ b/arch/um/os-Linux/aio.c @@ -313,15 +313,16 @@ static int init_aio_26(void) int err; if(io_setup(256, &ctx)){ + err = -errno; printk("aio_thread failed to initialize context, err = %d\n", errno); - return -errno; + return err; } err = run_helper_thread(aio_thread, NULL, CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0); if(err < 0) - return -errno; + return err; aio_pid = err; diff --git a/arch/um/os-Linux/drivers/tuntap_user.c b/arch/um/os-Linux/drivers/tuntap_user.c index 4b83c6c..4ba9b17 100644 --- a/arch/um/os-Linux/drivers/tuntap_user.c +++ b/arch/um/os-Linux/drivers/tuntap_user.c @@ -75,7 +75,7 @@ static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote, struct msghdr msg; struct cmsghdr *cmsg; struct iovec iov; - int pid, n; + int pid, n, err; 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); *used_out = n; if(n < 0){ + err = -errno; printk("tuntap_open_tramp : recvmsg failed - errno = %d\n", errno); - return(-errno); + return err; } CATCH_EINTR(waitpid(pid, NULL, 0)); @@ -147,9 +148,10 @@ static int tuntap_open(void *data) ifr.ifr_flags = IFF_TAP | IFF_NO_PI; strlcpy(ifr.ifr_name, pri->dev_name, sizeof(ifr.ifr_name)); if(ioctl(pri->fd, TUNSETIFF, (void *) &ifr) < 0){ + err = -errno; printk("TUNSETIFF failed, errno = %d\n", errno); os_close_file(pri->fd); - return(-errno); + return err; } } else { diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c index fd45bb2..f55773c 100644 --- a/arch/um/os-Linux/file.c +++ b/arch/um/os-Linux/file.c @@ -119,15 +119,11 @@ int os_window_size(int fd, int *rows, int *cols) int os_new_tty_pgrp(int fd, int pid) { - if(ioctl(fd, TIOCSCTTY, 0) < 0){ - printk("TIOCSCTTY failed, errno = %d\n", errno); - return(-errno); - } + if(ioctl(fd, TIOCSCTTY, 0) < 0) + return -errno; - if(tcsetpgrp(fd, pid) < 0){ - printk("tcsetpgrp failed, errno = %d\n", errno); - return(-errno); - } + if(tcsetpgrp(fd, pid) < 0) + return -errno; return(0); } @@ -146,18 +142,12 @@ int os_set_slip(int fd) int disc, sencap; disc = N_SLIP; - if(ioctl(fd, TIOCSETD, &disc) < 0){ - printk("Failed to set slip line discipline - " - "errno = %d\n", errno); - return(-errno); - } + if(ioctl(fd, TIOCSETD, &disc) < 0) + return -errno; sencap = 0; - if(ioctl(fd, SIOCSIFENCAP, &sencap) < 0){ - printk("Failed to set slip encapsulation - " - "errno = %d\n", errno); - return(-errno); - } + if(ioctl(fd, SIOCSIFENCAP, &sencap) < 0) + return -errno; return(0); } @@ -180,22 +170,15 @@ int os_sigio_async(int master, int slave) int flags; flags = fcntl(master, F_GETFL); - if(flags < 0) { - printk("fcntl F_GETFL failed, errno = %d\n", errno); - return(-errno); - } + if(flags < 0) + return errno; if((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) || - (fcntl(master, F_SETOWN, os_getpid()) < 0)){ - printk("fcntl F_SETFL or F_SETOWN failed, errno = %d\n", - errno); - return(-errno); - } + (fcntl(master, F_SETOWN, os_getpid()) < 0)) + return -errno; - if((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0)){ - printk("fcntl F_SETFL failed, errno = %d\n", errno); - return(-errno); - } + if((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0)) + return -errno; 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 fd, f = 0; + int fd, err, f = 0; if(flags.r && flags.w) f = O_RDWR; else if(flags.r) f = O_RDONLY; @@ -272,8 +255,9 @@ int os_open_file(char *file, struct openflags flags, int mode) return(-errno); if(flags.cl && fcntl(fd, F_SETFD, 1)){ + err = -errno; os_close_file(fd); - return(-errno); + return err; } return(fd); @@ -383,9 +367,9 @@ int os_file_size(char *file, unsigned long long *size_out) return(fd); } if(ioctl(fd, BLKGETSIZE, &blocks) < 0){ + err = -errno; printk("Couldn't get the block size of \"%s\", " "errno = %d\n", file, errno); - err = -errno; os_close_file(fd); 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 err; + /* XXX This should do F_GETFL first */ if(fcntl(fd, F_SETFL, O_ASYNC | O_NONBLOCK) < 0){ + err = -errno; printk("os_set_fd_async : failed to set O_ASYNC and " "O_NONBLOCK on fd # %d, errno = %d\n", fd, errno); - return(-errno); + return err; } #ifdef notdef 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) || (fcntl(fd, F_SETOWN, owner) < 0)){ + err = -errno; printk("os_set_fd_async : Failed to fcntl F_SETOWN " "(or F_SETSIG) fd %d to pid %d, errno = %d\n", fd, owner, errno); - return(-errno); + return err; } return(0); @@ -516,11 +504,9 @@ int os_set_fd_block(int fd, int blocking) if(blocking) flags &= ~O_NONBLOCK; else flags |= O_NONBLOCK; - if(fcntl(fd, F_SETFL, flags) < 0){ - printk("Failed to change blocking on fd # %d, errno = %d\n", - fd, errno); - return(-errno); - } + if(fcntl(fd, F_SETFL, flags) < 0) + return -errno; + return(0); } @@ -609,11 +595,8 @@ int os_create_unix_socket(char *file, int len, int close_on_exec) int sock, err; sock = socket(PF_UNIX, SOCK_DGRAM, 0); - if (sock < 0){ - printk("create_unix_socket - socket failed, errno = %d\n", - errno); - return(-errno); - } + if(sock < 0) + return -errno; if(close_on_exec) { 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); err = bind(sock, (struct sockaddr *) &addr, sizeof(addr)); - if (err < 0){ - printk("create_listening_socket at '%s' - bind failed, " - "errno = %d\n", file, errno); - return(-errno); - } + if(err < 0) + return -errno; return(sock); } |