Hi,
The following diff simplifies the check for allowing only promises
reductions.
Please review it carefully: it implies several bitwise operations.
I will try also to explain the diff step-by-step because even if it is
small in size, it manipulates lot of things.
1. removing: flags &= p->p_p->ps_pledge;
`flags' is the result of parsing user promises string. It is builded
using pledgereq_flags() function, and will contains only the requested
flags (no _USERSET flags).
Just before, we have checked that `flags' is a subset of `ps_pledge'. So
we could use it directly, without using ps_pledge as mask. The
expression would set `flags' to intersection between flags list of
promises and ps_pledge list of promises, but as `flags' is already a subset
of `ps_pledge' it is unneeded.
2. removing: flags &= PLEDGE_USERSET;
this one ensure that `flags' contains only bitflags in _USERSET part.
Due to pledgereq_flags(), it is necessary the case, so it is unneeded
and could be removed too.
3. remove mask to PLEDGE_USERSET in conditionnal
`ps_pledge' could containing promises bitflags from user promises and
bitflags from kernel (like PLEDGE_YPACTIVE). `flags' could only have
user promises.
comparaison of (flags|ps_pledge) & USERSET != ps_pledge & USERSET
and (flags|ps_pledge) != ps_pledge
should have some result. We still ensure that `flags' doesn't contains
any extra bits that `ps_pledge' doesn't have.
(The diff was generated in a way it doesn't depend on previous one)
Comments ?
--
Sebastien Marie
Index: kern/kern_pledge.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_pledge.c,v
retrieving revision 1.162
diff -u -p -r1.162 kern_pledge.c
--- kern/kern_pledge.c 30 Mar 2016 07:49:11 -0000 1.162
+++ kern/kern_pledge.c 10 Apr 2016 12:12:04 -0000
@@ -437,16 +437,14 @@ sys_pledge(struct proc *p, void *v, regi
if (flags & ~PLEDGE_USERSET)
return (EINVAL);
- if ((p->p_p->ps_flags & PS_PLEDGE)) {
- /* Already pledged, only allow reductions */
- if (((flags | p->p_p->ps_pledge) & PLEDGE_USERSET) !=
- (p->p_p->ps_pledge & PLEDGE_USERSET)) {
- return (EPERM);
- }
-
- flags &= p->p_p->ps_pledge;
- flags &= PLEDGE_USERSET; /* Relearn _ACTIVE */
- }
+ /*
+ * if we are already pledged, allow only promises reductions.
+ * flags doesn't contain flags outside _USERSET: they will be
+ * relearned.
+ */
+ if (ISSET(p->p_p->ps_flags, PS_PLEDGE) &&
+ (((flags | p->p_p->ps_pledge) != p->p_p->ps_pledge)))
+ return (EPERM);
}
if (SCARG(uap, paths)) {