Mark get*[ug]id() as NOLOCK

2014-07-07 Thread Matthew Dempsky
Recently guenther changed user credentials to be a per-process
resource, but kept a per-thread cache of credentials that get
refreshed at each system call entry.  All of the get*[ug]id() system
calls simply access the thread cached credentials, and possibly
copyout() them if necessary, so they're safe to mark as NOLOCK.

ok?


Index: syscalls.master
===
RCS file: /cvs/src/sys/kern/syscalls.master,v
retrieving revision 1.141
diff -u -p -r1.141 syscalls.master
--- syscalls.master 6 Jul 2014 20:55:58 -   1.141
+++ syscalls.master 7 Jul 2014 18:06:34 -
@@ -80,8 +80,8 @@
int flags, void *data); }
 22 STD { int sys_unmount(const char *path, int flags); }
 23 STD { int sys_setuid(uid_t uid); }
-24 STD { uid_t sys_getuid(void); }
-25 STD { uid_t sys_geteuid(void); }
+24 STD NOLOCK  { uid_t sys_getuid(void); }
+25 STD NOLOCK  { uid_t sys_geteuid(void); }
 #ifdef PTRACE
 26 STD { int sys_ptrace(int req, pid_t pid, caddr_t addr, \
int data); }
@@ -112,7 +112,7 @@
 41 STD { int sys_dup(int fd); }
 42 STD { int sys_fstatat(int fd, const char *path, \
struct stat *buf, int flag); }
-43 STD { gid_t sys_getegid(void); }
+43 STD NOLOCK  { gid_t sys_getegid(void); }
 44 STD { int sys_profil(caddr_t samples, size_t size, \
u_long offset, u_int scale); }
 #ifdef KTRACE
@@ -124,7 +124,7 @@
 46 STD { int sys_sigaction(int signum, \
const struct sigaction *nsa, \
struct sigaction *osa); }
-47 STD { gid_t sys_getgid(void); }
+47 STD NOLOCK  { gid_t sys_getgid(void); }
 48 STD { int sys_sigprocmask(int how, sigset_t mask); }
 49 STD { int sys_getlogin(char *namebuf, u_int namelen); }
 50 STD { int sys_setlogin(const char *namebuf); }
@@ -181,7 +181,7 @@
const struct timeval *tptr); }
 78 STD { int sys_mincore(void *addr, size_t len, \
char *vec); }
-79 STD { int sys_getgroups(int gidsetsize, \
+79 STD NOLOCK  { int sys_getgroups(int gidsetsize, \
gid_t *gidset); }
 80 STD { int sys_setgroups(int gidsetsize, \
const gid_t *gidset); }
@@ -476,11 +476,11 @@
 278UNIMPL  sys_extattr_set_fd
 279UNIMPL  sys_extattr_get_fd
 280UNIMPL  sys_extattr_delete_fd
-281STD { int sys_getresuid(uid_t *ruid, uid_t *euid, \
+281STD NOLOCK  { int sys_getresuid(uid_t *ruid, uid_t *euid, \
uid_t *suid); }
 282STD { int sys_setresuid(uid_t ruid, uid_t euid, \
uid_t suid); }
-283STD { int sys_getresgid(gid_t *rgid, gid_t *egid, \
+283STD NOLOCK  { int sys_getresgid(gid_t *rgid, gid_t *egid, \
gid_t *sgid); }
 284STD { int sys_setresgid(gid_t rgid, gid_t egid, \
gid_t sgid); }



Re: Mark get*[ug]id() as NOLOCK

2014-07-07 Thread Mark Kettenis
 Date: Mon, 7 Jul 2014 11:18:53 -0700
 From: Matthew Dempsky matt...@dempsky.org
 
 Recently guenther changed user credentials to be a per-process
 resource, but kept a per-thread cache of credentials that get
 refreshed at each system call entry.  All of the get*[ug]id() system
 calls simply access the thread cached credentials, and possibly
 copyout() them if necessary, so they're safe to mark as NOLOCK.
 
 ok?

Makes sense to me.  But let's give guenther@ a chance to comment.

 Index: syscalls.master
 ===
 RCS file: /cvs/src/sys/kern/syscalls.master,v
 retrieving revision 1.141
 diff -u -p -r1.141 syscalls.master
 --- syscalls.master   6 Jul 2014 20:55:58 -   1.141
 +++ syscalls.master   7 Jul 2014 18:06:34 -
 @@ -80,8 +80,8 @@
   int flags, void *data); }
  22   STD { int sys_unmount(const char *path, int flags); }
  23   STD { int sys_setuid(uid_t uid); }
 -24   STD { uid_t sys_getuid(void); }
 -25   STD { uid_t sys_geteuid(void); }
 +24   STD NOLOCK  { uid_t sys_getuid(void); }
 +25   STD NOLOCK  { uid_t sys_geteuid(void); }
  #ifdef PTRACE
  26   STD { int sys_ptrace(int req, pid_t pid, caddr_t addr, \
   int data); }
 @@ -112,7 +112,7 @@
  41   STD { int sys_dup(int fd); }
  42   STD { int sys_fstatat(int fd, const char *path, \
   struct stat *buf, int flag); }
 -43   STD { gid_t sys_getegid(void); }
 +43   STD NOLOCK  { gid_t sys_getegid(void); }
  44   STD { int sys_profil(caddr_t samples, size_t size, \
   u_long offset, u_int scale); }
  #ifdef KTRACE
 @@ -124,7 +124,7 @@
  46   STD { int sys_sigaction(int signum, \
   const struct sigaction *nsa, \
   struct sigaction *osa); }
 -47   STD { gid_t sys_getgid(void); }
 +47   STD NOLOCK  { gid_t sys_getgid(void); }
  48   STD { int sys_sigprocmask(int how, sigset_t mask); }
  49   STD { int sys_getlogin(char *namebuf, u_int namelen); }
  50   STD { int sys_setlogin(const char *namebuf); }
 @@ -181,7 +181,7 @@
   const struct timeval *tptr); }
  78   STD { int sys_mincore(void *addr, size_t len, \
   char *vec); }
 -79   STD { int sys_getgroups(int gidsetsize, \
 +79   STD NOLOCK  { int sys_getgroups(int gidsetsize, \
   gid_t *gidset); }
  80   STD { int sys_setgroups(int gidsetsize, \
   const gid_t *gidset); }
 @@ -476,11 +476,11 @@
  278  UNIMPL  sys_extattr_set_fd
  279  UNIMPL  sys_extattr_get_fd
  280  UNIMPL  sys_extattr_delete_fd
 -281  STD { int sys_getresuid(uid_t *ruid, uid_t *euid, \
 +281  STD NOLOCK  { int sys_getresuid(uid_t *ruid, uid_t *euid, \
   uid_t *suid); }
  282  STD { int sys_setresuid(uid_t ruid, uid_t euid, \
   uid_t suid); }
 -283  STD { int sys_getresgid(gid_t *rgid, gid_t *egid, \
 +283  STD NOLOCK  { int sys_getresgid(gid_t *rgid, gid_t *egid, \
   gid_t *sgid); }
  284  STD { int sys_setresgid(gid_t rgid, gid_t egid, \
   gid_t sgid); }
 
 



Re: Mark get*[ug]id() as NOLOCK

2014-07-07 Thread Ted Unangst
On Mon, Jul 07, 2014 at 11:18, Matthew Dempsky wrote:
 Recently guenther changed user credentials to be a per-process
 resource, but kept a per-thread cache of credentials that get
 refreshed at each system call entry.  All of the get*[ug]id() system
 calls simply access the thread cached credentials, and possibly
 copyout() them if necessary, so they're safe to mark as NOLOCK.


Is copyout safe to call with no lock?



Re: Mark get*[ug]id() as NOLOCK

2014-07-07 Thread Mark Kettenis
 Date: Mon, 07 Jul 2014 15:06:47 -0400
 From: Ted Unangst t...@tedunangst.com
 
 On Mon, Jul 07, 2014 at 11:18, Matthew Dempsky wrote:
  Recently guenther changed user credentials to be a per-process
  resource, but kept a per-thread cache of credentials that get
  refreshed at each system call entry.  All of the get*[ug]id() system
  calls simply access the thread cached credentials, and possibly
  copyout() them if necessary, so they're safe to mark as NOLOCK.
 
 Is copyout safe to call with no lock?

yes



Re: Mark get*[ug]id() as NOLOCK

2014-07-07 Thread Philip Guenther
On Mon, Jul 7, 2014 at 11:18 AM, Matthew Dempsky matt...@dempsky.org
wrote:

 Recently guenther changed user credentials to be a per-process
 resource, but kept a per-thread cache of credentials that get
 refreshed at each system call entry.  All of the get*[ug]id() system
 calls simply access the thread cached credentials, and possibly
 copyout() them if necessary, so they're safe to mark as NOLOCK.

 ok?


Oh yeah, I knew there was another benefit to that work.  Thanks!  ok
guenther@


Use atomics for mutating p_sigmask

2014-07-07 Thread Matthew Dempsky
p_sigmask is only modified by the owning thread from process context
(e.g., sys_sigprocmask(), sys_sigreturn(), userret(), or postsig()),
but it can be accessed anywhere (e.g., interrupts or threads on other
CPUs).  Currently sys_sigprocmask() protects p_sigmask with splhigh(),
but that's not MP-safe.

The simpler solution is to take advantage of our atomics APIs.
Unfortunately for implementing SIG_SETMASK, we don't have an
atomic_store_int() function, and I can't bring myself to abuse
volatile for this purpose, so I've resorted to atomic_swap_uint().

While here, I also refactored the P_SIGSUSPEND code a bit so there's
less code duplication.

I've included just amd64 and i386's machdep.c for now, because those
were the only ones I'm readily able to test.  The others should be
easy to similarly fix though, and I can send a followup diff for them.

ok?


Index: sys/proc.h
===
RCS file: /home/matthew/cvs-mirror/cvs/src/sys/sys/proc.h,v
retrieving revision 1.186
diff -u -p -r1.186 proc.h
--- sys/proc.h  15 May 2014 03:52:25 -  1.186
+++ sys/proc.h  7 Jul 2014 19:23:06 -
@@ -520,6 +520,8 @@ int proc_cansugid(struct proc *);
 void   proc_finish_wait(struct proc *, struct proc *);
 void   process_zap(struct process *);
 void   proc_free(struct proc *);
+void   proc_sigsetmask(struct proc *, sigset_t);
+void   proc_sigsuspend(struct proc *, sigset_t);
 
 struct sleep_state {
int sls_s;
@@ -559,4 +561,3 @@ struct cpu_info *cpuset_first(struct cpu
 
 #endif /* _KERNEL */
 #endif /* !_SYS_PROC_H_ */
-
Index: kern/kern_sig.c
===
RCS file: /home/matthew/cvs-mirror/cvs/src/sys/kern/kern_sig.c,v
retrieving revision 1.166
diff -u -p -r1.166 kern_sig.c
--- kern/kern_sig.c 4 May 2014 05:03:26 -   1.166
+++ kern/kern_sig.c 7 Jul 2014 19:24:07 -
@@ -62,6 +62,7 @@
 #include sys/ptrace.h
 #include sys/sched.h
 #include sys/user.h
+#include sys/atomic.h
 
 #include sys/mount.h
 #include sys/syscallargs.h
@@ -439,37 +440,55 @@ sys_sigprocmask(struct proc *p, void *v,
syscallarg(int) how;
syscallarg(sigset_t) mask;
} */ *uap = v;
-   int error = 0;
-   int s;
-   sigset_t mask;
+   sigset_t mask = SCARG(uap, mask);
 
*retval = p-p_sigmask;
-   mask = SCARG(uap, mask);
-   s = splhigh();
 
switch (SCARG(uap, how)) {
case SIG_BLOCK:
-   p-p_sigmask |= mask ~ sigcantmask;
+   atomic_setbits_int(p-p_sigmask, mask ~ sigcantmask);
break;
case SIG_UNBLOCK:
-   p-p_sigmask = ~mask;
+   atomic_clearbits_int(p-p_sigmask, mask);
break;
case SIG_SETMASK:
-   p-p_sigmask = mask ~ sigcantmask;
+   proc_sigsetmask(p, mask ~ sigcantmask);
break;
default:
-   error = EINVAL;
-   break;
+   return (EINVAL);
}
-   splx(s);
-   return (error);
+
+   return (0);
+}
+
+void
+proc_sigsetmask(struct proc *p, sigset_t mask)
+{
+   KASSERT(p == curproc);
+
+   /* XXX: An atomic store would suffice here. */
+   (void)atomic_swap_uint(p-p_sigmask, mask);
+}
+
+/*
+ * Temporarily replace calling proc's signal mask for the duration of a
+ * system call.  Original signal mask will be restored by userret().
+ */
+void
+proc_sigsuspend(struct proc *p, sigset_t mask)
+{
+   KASSERT(p == curproc);
+   KASSERT(!(p-p_flag  P_SIGSUSPEND));
+
+   p-p_oldmask = p-p_sigmask;
+   atomic_setbits_int(p-p_flag, P_SIGSUSPEND);
+   proc_sigsetmask(p, mask);
 }
 
 /* ARGSUSED */
 int
 sys_sigpending(struct proc *p, void *v, register_t *retval)
 {
-
*retval = p-p_siglist;
return (0);
 }
@@ -489,16 +508,7 @@ sys_sigsuspend(struct proc *p, void *v, 
struct process *pr = p-p_p;
struct sigacts *ps = pr-ps_sigacts;
 
-   /*
-* When returning from sigpause, we want
-* the old mask to be restored after the
-* signal handler has finished.  Thus, we
-* save it here and mark the sigacts structure
-* to indicate this.
-*/
-   p-p_oldmask = p-p_sigmask;
-   atomic_setbits_int(p-p_flag, P_SIGSUSPEND);
-   p-p_sigmask = SCARG(uap, mask) ~ sigcantmask;
+   proc_sigsuspend(p, SCARG(uap, mask) ~ sigcantmask);
while (tsleep(ps, PPAUSE|PCATCH, pause, 0) == 0)
/* void */;
/* always return EINTR rather than ERESTART... */
Index: kern/sys_generic.c
===
RCS file: /home/matthew/cvs-mirror/cvs/src/sys/kern/sys_generic.c,v
retrieving revision 1.86
diff -u -p -r1.86 sys_generic.c
--- kern/sys_generic.c  30 Mar 2014 21:54:48 -  1.86
+++ kern/sys_generic.c  7 Jul 2014 19:24:07 -
@@ -658,9 +620,7 @@ dopselect(struct proc