Messages in this thread | | | Date | Mon, 27 Jul 2015 21:19:15 +0200 | From | Denys Vlasenko <> | Subject | Re: [PATCH 2/3] x86/asm/entry/32: Remove most of SYSCALL32 code, part 1 |
| |
On 07/24/2015 07:50 PM, Andy Lutomirski wrote: > On Fri, Jul 24, 2015 at 6:47 AM, Denys Vlasenko <dvlasenk@redhat.com> wrote: >> SYSCALL32 code is nearly identical to SYSCALL32, except for initial >> section. Merge them. >> >> The removal is split into two parts, to make review eaiser. This is part 1. >> >> auditsys_entry_common and auditsys_exit macros are indented one more tab without >> any changes. This prevents diff from becoming unreadable. >> They will be removed in part 2. > > I need to read these more closely, which is, at present, exceeding my > ability to look at asm. (See the big NMI thread.) I'll look soon. > > Meanwhile, this code is incredibly fragile wrt syscall restart. > (Syscall restart on compat is really weird.) Do we have a decent test > for it?
How about this? (Feel free to expand, this is a first cut only).
$ ./test_restart [RUN] Test restart of read() [OK] Restart of read() worked [RUN] Test restart of recv() [OK] Restart of recv() worked
#undef _GNU_SOURCE #define _GNU_SOURCE 1 #undef __USE_GNU #define __USE_GNU 1 #include <unistd.h> #include <stdlib.h> #include <string.h> #include <stdio.h> #include <signal.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/select.h> #include <sys/time.h> //#include <sys/ptrace.h> #include <sys/wait.h>
void signal_SA_RESTART_empty_mask(int sig, void (*handler)(int)) { struct sigaction sa; memset(&sa, 0, sizeof(sa)); sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; sa.sa_handler = handler; sigaction(sig, &sa, NULL); }
int make_writer(void) { int pid, fd[2]; if (pipe(fd)) exit(1); pid = fork(); if (pid < 0) exit(1); if (pid == 0) { /* child */ usleep(50*1000); write(fd[1], "123456789", 10); exit(0); } close(fd[1]); return fd[0]; }
int make_sender(void) { int pid, fd[2]; if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd)) exit(1); pid = fork(); if (pid < 0) exit(1); if (pid == 0) { /* child */ usleep(50*1000); write(fd[1], "123456789", 10); exit(0); } close(fd[1]); return fd[0]; }
int got_sig;
void sighandler(int sig) { got_sig = 1; }
void prepare(char buf[10]) { got_sig = 0; strcpy(buf, "qwertyuio"); ualarm(25*1000, 0); }
int check(const char *test_type, int len, char buf[10]) { int err = 0; if (len != 10 || strcmp(buf, "123456789") != 0) { printf("[FAIL]\tRestarted %s() returns wrong result\n", test_type); err = 1; } if (!got_sig) { printf("[FAIL]\tSignal was expected on %s read() but wasn't seen\n", test_type); err = 1; } if (!err) printf("[OK]\tRestart of %s() worked\n", test_type); return err; }
int main(int argc, char **argv, char **envp) { char buf[10]; int fd; int len; int err;
signal_SA_RESTART_empty_mask(SIGALRM, sighandler);
printf("[RUN]\tTest restart of read()\n"); fd = make_writer(); prepare(buf); len = read(fd, buf, 10); err = check("read", len, buf); close(fd);
printf("[RUN]\tTest restart of recv()\n"); fd = make_sender(); prepare(buf); len = recv(fd, buf, 10, MSG_PEEK); err |= check("recv", len, buf); if (!err) { /* Check that restarted recv() indeed had MSG_PEEK: * i.e. that it did not consume the data. */ strcpy(buf, "qwertyuio"); len = recv(fd, buf, 10, 0); if (len != 10 || strcmp(buf, "123456789") != 0) { printf("[FAIL]\tRestarted %s() had no MSG_PEEK flag\n", "recv"); err = 1; } } close(fd);
return err; }
| |