mirror of
https://github.com/drasko/codezero.git
synced 2026-04-17 17:29:04 +02:00
Capability replicate/split/destroy/grant working for test0 ipc.
Implemented a protocol between a client and its pager to request and get a capability to ipc to another client of the pager. Pager first ensures the request is valid from its client. It then tries to use a greater capability that it possesses, to produce a new capability that the client requested. Once the kernel validates the correct one and replicates/reduces it to client's need, it grants it to the client.
This commit is contained in:
@@ -347,73 +347,86 @@ int cap_find_replicate_reduce_grant(struct capability *cap)
|
|||||||
struct capability new_cap;
|
struct capability new_cap;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
/*
|
/* Merely match type, kernel does actual check on suitability */
|
||||||
* Check for type
|
|
||||||
*/
|
|
||||||
list_foreach_struct(possessed, &capability_list.caps, list) {
|
list_foreach_struct(possessed, &capability_list.caps, list) {
|
||||||
if (cap_type(possessed) == cap_type(cap))
|
/* Different type, pass */
|
||||||
goto found;
|
if (cap_type(possessed) != cap_type(cap))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Copy possessed one to new one's buffer */
|
||||||
|
memcpy(&new_cap, possessed, sizeof(*possessed));
|
||||||
|
|
||||||
|
/* Replicate capability, giving original as reference */
|
||||||
|
if ((err = l4_capability_control(CAP_CONTROL_REPLICATE,
|
||||||
|
0, 0, 0, &new_cap)) < 0) {
|
||||||
|
printf("l4_capability_control() replication of "
|
||||||
|
"capability failed.\n Could not complete "
|
||||||
|
"CAP_CONTROL_REPLICATE request on cap (%d), "
|
||||||
|
"err = %d.\n", new_cap.capid, err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The returned capability is a replica.
|
||||||
|
*
|
||||||
|
* We don't add the newly created one to our own internal
|
||||||
|
* list because we will grant it shortly and lose its
|
||||||
|
* possession
|
||||||
|
*
|
||||||
|
* Now deduce it such that it looks like the one requested.
|
||||||
|
* Note, we assume the request had been validated before.
|
||||||
|
* Also note, the owner shall be still us.
|
||||||
|
*/
|
||||||
|
new_cap.resid = cap->resid;
|
||||||
|
new_cap.type = cap->type;
|
||||||
|
new_cap.access = cap->access;
|
||||||
|
new_cap.start = cap->start;
|
||||||
|
new_cap.end = cap->end;
|
||||||
|
new_cap.size = cap->size;
|
||||||
|
new_cap.used = cap->used;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make sure it is transferable,
|
||||||
|
* since we will need to grant it soon
|
||||||
|
*/
|
||||||
|
new_cap.access |= CAP_TRANSFERABLE;
|
||||||
|
|
||||||
|
|
||||||
|
if ((err = l4_capability_control(CAP_CONTROL_DEDUCE,
|
||||||
|
0, 0, 0, &new_cap)) < 0) {
|
||||||
|
/* Couldn't deduce this one, destroy the replica */
|
||||||
|
if ((err =
|
||||||
|
l4_capability_control(CAP_CONTROL_DESTROY,
|
||||||
|
0, 0, 0, &new_cap)) < 0) {
|
||||||
|
printf("l4_capability_control() replication of "
|
||||||
|
"capability failed.\n Could not "
|
||||||
|
"complete CAP_CONTROL_DESTROY request "
|
||||||
|
" on cap (%d), err = %d.\n",
|
||||||
|
new_cap.capid, err);
|
||||||
|
BUG();
|
||||||
|
}
|
||||||
|
} else /* Success */
|
||||||
|
goto success;
|
||||||
}
|
}
|
||||||
|
|
||||||
return -ENOCAP;
|
return -ENOCAP;
|
||||||
|
|
||||||
found:
|
success:
|
||||||
/* Copy possessed one to new one's buffer */
|
|
||||||
memcpy(&new_cap, possessed, sizeof(*possessed));
|
|
||||||
|
|
||||||
/* Replicate the possessed capability, giving original as reference */
|
|
||||||
if ((err = l4_capability_control(CAP_CONTROL_REPLICATE,
|
|
||||||
0, 0, 0, &new_cap)) < 0) {
|
|
||||||
printf("l4_capability_control() replication of "
|
|
||||||
"capability failed.\n Could not "
|
|
||||||
"complete CAP_CONTROL_REPLICATE request on cap (%d), "
|
|
||||||
"err = %d.\n", new_cap.capid, err);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The returned capability is a replica.
|
* Found suitable one to replicate/deduce.
|
||||||
|
* Grant it to requested owner.
|
||||||
*
|
*
|
||||||
* We don't add the newly created one to our own internal
|
* This effectively enables the owner to have all
|
||||||
* list because we will grant it shortly and lose its
|
* operations defined in the capability. However,
|
||||||
* possession
|
* we use a flag to make the capability immutable
|
||||||
*
|
* as we grant it. (We wouldn't be able to grant
|
||||||
* Now deduce it such that it looks like the one requested.
|
* it if it had no grant permission originally. We
|
||||||
* Note, we assume the request had been validated before.
|
* remove it _as_ we grant it)
|
||||||
*/
|
|
||||||
new_cap.owner = cap->owner;
|
|
||||||
new_cap.resid = cap->resid;
|
|
||||||
new_cap.type = cap->type;
|
|
||||||
new_cap.access = cap->access;
|
|
||||||
new_cap.start = cap->start;
|
|
||||||
new_cap.end = cap->end;
|
|
||||||
new_cap.size = cap->size;
|
|
||||||
new_cap.used = cap->used;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Make sure it is transferable,
|
|
||||||
* since we will need to grant it soon
|
|
||||||
*/
|
|
||||||
new_cap.access |= CAP_TRANSFERABLE;
|
|
||||||
|
|
||||||
if ((err = l4_capability_control(CAP_CONTROL_DEDUCE,
|
|
||||||
0, 0, 0, &new_cap)) < 0) {
|
|
||||||
printf("l4_capability_control() deduction of "
|
|
||||||
"ipc capability failed.\n Could not "
|
|
||||||
"complete CAP_CONTROL_DEDUCE request on cap (%d), "
|
|
||||||
"err = %d.\n", new_cap.capid, err);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Grant it to given owner.
|
|
||||||
*
|
|
||||||
* This effectively enables the owner to have all operations defined
|
|
||||||
* in the capability. However, we use a flag to make the capability
|
|
||||||
* immutable as we grant it. (We wouldn't be able to grant it if it
|
|
||||||
* had no grant permission originally. We remove it as we grant it)
|
|
||||||
*/
|
*/
|
||||||
|
new_cap.owner = cap->owner; /* Indicate new owner */
|
||||||
if ((err = l4_capability_control(CAP_CONTROL_GRANT,
|
if ((err = l4_capability_control(CAP_CONTROL_GRANT,
|
||||||
CAP_GRANT_SINGLE | CAP_GRANT_IMMUTABLE,
|
CAP_GRANT_SINGLE |
|
||||||
|
CAP_GRANT_IMMUTABLE,
|
||||||
0, 0, &new_cap)) < 0) {
|
0, 0, &new_cap)) < 0) {
|
||||||
printf("l4_capability_control() granting of "
|
printf("l4_capability_control() granting of "
|
||||||
"capability (%d) failed.\n Could not "
|
"capability (%d) failed.\n Could not "
|
||||||
@@ -493,8 +506,7 @@ int sys_request_cap(struct tcb *task, struct capability *__cap_userptr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
pager_unmap_user_range(__cap_userptr,
|
pager_unmap_user_range(cap, sizeof(*cap));
|
||||||
sizeof(*__cap_userptr));
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -105,11 +105,11 @@ void ipc_extended_test(void)
|
|||||||
cap.owner = parent;
|
cap.owner = parent;
|
||||||
cap.resid = child;
|
cap.resid = child;
|
||||||
} else {
|
} else {
|
||||||
cap.owner = child;
|
cap.owner = getpid();
|
||||||
cap.resid = parent;
|
cap.resid = parent;
|
||||||
}
|
}
|
||||||
cap.type = CAP_TYPE_IPC | CAP_RTYPE_THREAD;
|
cap.type = CAP_TYPE_IPC | CAP_RTYPE_THREAD;
|
||||||
cap.access = CAP_IPC_EXTENDED;
|
cap.access = CAP_IPC_EXTENDED | CAP_IPC_SEND | CAP_IPC_RECV;
|
||||||
if ((err = cap_request_pager(&cap)) < 0) {
|
if ((err = cap_request_pager(&cap)) < 0) {
|
||||||
printf("Ipc capability request failed. "
|
printf("Ipc capability request failed. "
|
||||||
"err = %d\n", err);
|
"err = %d\n", err);
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
#define CAP_CONTROL_REPLICATE 0x00000005
|
#define CAP_CONTROL_REPLICATE 0x00000005
|
||||||
#define CAP_CONTROL_SPLIT 0x00000006
|
#define CAP_CONTROL_SPLIT 0x00000006
|
||||||
#define CAP_CONTROL_DEDUCE 0x00000007
|
#define CAP_CONTROL_DEDUCE 0x00000007
|
||||||
|
#define CAP_CONTROL_DESTROY 0x00000008
|
||||||
|
|
||||||
#define CAP_SHARE_MASK 0x00000003
|
#define CAP_SHARE_MASK 0x00000003
|
||||||
#define CAP_SHARE_SINGLE 0x00000001
|
#define CAP_SHARE_SINGLE 0x00000001
|
||||||
|
|||||||
@@ -108,6 +108,7 @@
|
|||||||
#define CAP_CAP_REPLICATE (1 << 3)
|
#define CAP_CAP_REPLICATE (1 << 3)
|
||||||
#define CAP_CAP_SPLIT (1 << 4)
|
#define CAP_CAP_SPLIT (1 << 4)
|
||||||
#define CAP_CAP_DEDUCE (1 << 5)
|
#define CAP_CAP_DEDUCE (1 << 5)
|
||||||
#define CAP_CAP_MODIFY (CAP_CAP_SPLIT | CAP_CAP_DEDUCE)
|
#define CAP_CAP_DESTROY (1 << 6)
|
||||||
|
#define CAP_CAP_MODIFY (CAP_CAP_DEDUCE | CAP_CAP_SPLIT \
|
||||||
|
| CAP_CAP_DESTROY)
|
||||||
#endif /* __CAP_TYPES_H__ */
|
#endif /* __CAP_TYPES_H__ */
|
||||||
|
|||||||
@@ -99,6 +99,13 @@ static inline void cap_list_insert(struct capability *cap,
|
|||||||
clist->ncaps++;
|
clist->ncaps++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void cap_list_remove(struct capability *cap,
|
||||||
|
struct cap_list *clist)
|
||||||
|
{
|
||||||
|
list_remove(&cap->list);
|
||||||
|
clist->ncaps--;
|
||||||
|
}
|
||||||
|
|
||||||
/* Detach a whole list of capabilities from list head */
|
/* Detach a whole list of capabilities from list head */
|
||||||
static inline struct capability *
|
static inline struct capability *
|
||||||
cap_list_detach(struct cap_list *clist)
|
cap_list_detach(struct cap_list *clist)
|
||||||
@@ -141,6 +148,8 @@ struct capability *cap_list_find_by_rtype(struct cap_list *clist,
|
|||||||
unsigned int rtype);
|
unsigned int rtype);
|
||||||
struct capability *cap_find_byid(l4id_t capid);
|
struct capability *cap_find_byid(l4id_t capid);
|
||||||
|
|
||||||
|
int cap_find_destroy(l4id_t capid);
|
||||||
|
|
||||||
/* Capability checking on system calls */
|
/* Capability checking on system calls */
|
||||||
int cap_map_check(struct ktcb *task, unsigned long phys, unsigned long virt,
|
int cap_map_check(struct ktcb *task, unsigned long phys, unsigned long virt,
|
||||||
unsigned long npages, unsigned int flags);
|
unsigned long npages, unsigned int flags);
|
||||||
|
|||||||
@@ -97,13 +97,14 @@ int cap_share(l4id_t capid, unsigned int flags)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Grants all caps */
|
/* Grants all caps */
|
||||||
int cap_grant_all(l4id_t tid, unsigned int flags)
|
int cap_grant_all(struct capability *req, unsigned int flags)
|
||||||
{
|
{
|
||||||
struct ktcb *target;
|
struct ktcb *target;
|
||||||
struct capability *cap_head, *cap;
|
struct capability *cap_head, *cap;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (!(target = tcb_find(tid)))
|
/* Owners are always threads, for simplicity */
|
||||||
|
if (!(target = tcb_find(req->owner)))
|
||||||
return -ESRCH;
|
return -ESRCH;
|
||||||
|
|
||||||
/* Detach all caps */
|
/* Detach all caps */
|
||||||
@@ -112,6 +113,7 @@ int cap_grant_all(l4id_t tid, unsigned int flags)
|
|||||||
list_foreach_struct(cap, &cap_head->list, list) {
|
list_foreach_struct(cap, &cap_head->list, list) {
|
||||||
/* Change ownership */
|
/* Change ownership */
|
||||||
cap->owner = target->tid;
|
cap->owner = target->tid;
|
||||||
|
BUG_ON(target->tid != req->owner);
|
||||||
|
|
||||||
/* Make immutable if GRANT_IMMUTABLE given */
|
/* Make immutable if GRANT_IMMUTABLE given */
|
||||||
if (flags & CAP_GRANT_IMMUTABLE) {
|
if (flags & CAP_GRANT_IMMUTABLE) {
|
||||||
@@ -140,15 +142,15 @@ out_err:
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cap_grant_single(l4id_t capid, l4id_t tid, unsigned int flags)
|
int cap_grant_single(struct capability *req, unsigned int flags)
|
||||||
{
|
{
|
||||||
struct capability *cap;
|
struct capability *cap;
|
||||||
struct ktcb *target;
|
struct ktcb *target;
|
||||||
|
|
||||||
if (!(cap = cap_find_byid(capid)))
|
if (!(cap = cap_find_byid(req->capid)))
|
||||||
return -EEXIST;
|
return -EEXIST;
|
||||||
|
|
||||||
if (!(target = tcb_find(tid)))
|
if (!(target = tcb_find(req->owner)))
|
||||||
return -ESRCH;
|
return -ESRCH;
|
||||||
|
|
||||||
if (cap->owner != current->tid)
|
if (cap->owner != current->tid)
|
||||||
@@ -163,6 +165,7 @@ int cap_grant_single(l4id_t capid, l4id_t tid, unsigned int flags)
|
|||||||
|
|
||||||
/* Change ownership */
|
/* Change ownership */
|
||||||
cap->owner = target->tid;
|
cap->owner = target->tid;
|
||||||
|
BUG_ON(cap->owner != req->owner);
|
||||||
|
|
||||||
/* Make immutable if GRANT_IMMUTABLE given */
|
/* Make immutable if GRANT_IMMUTABLE given */
|
||||||
if (flags & CAP_GRANT_IMMUTABLE) {
|
if (flags & CAP_GRANT_IMMUTABLE) {
|
||||||
@@ -176,12 +179,12 @@ int cap_grant_single(l4id_t capid, l4id_t tid, unsigned int flags)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cap_grant(l4id_t capid, l4id_t tid, unsigned int flags)
|
int cap_grant(struct capability *cap, unsigned int flags)
|
||||||
{
|
{
|
||||||
if (flags & CAP_GRANT_SINGLE)
|
if (flags & CAP_GRANT_SINGLE)
|
||||||
cap_grant_single(capid, tid, flags);
|
cap_grant_single(cap, flags);
|
||||||
else if (flags & CAP_GRANT_ALL)
|
else if (flags & CAP_GRANT_ALL)
|
||||||
cap_grant_all(tid, flags);
|
cap_grant_all(cap, flags);
|
||||||
else
|
else
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
return 0;
|
return 0;
|
||||||
@@ -288,6 +291,10 @@ int cap_deduce(struct capability *new)
|
|||||||
if ((ret = cap_deduce_rtype(orig, new)) < 0)
|
if ((ret = cap_deduce_rtype(orig, new)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
/* Check owners are same for request validity */
|
||||||
|
if (orig->owner != new->owner)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
/* Check permissions for deduction */
|
/* Check permissions for deduction */
|
||||||
if (orig->access) {
|
if (orig->access) {
|
||||||
/* New cannot have more bits than original */
|
/* New cannot have more bits than original */
|
||||||
@@ -340,6 +347,29 @@ int cap_deduce(struct capability *new)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Destroys a capability
|
||||||
|
*/
|
||||||
|
int cap_destroy(struct capability *cap)
|
||||||
|
{
|
||||||
|
struct capability *orig;
|
||||||
|
|
||||||
|
/* Find original capability */
|
||||||
|
if (!(orig = cap_find_byid(cap->capid)))
|
||||||
|
return -EEXIST;
|
||||||
|
|
||||||
|
/* Check that caller is owner */
|
||||||
|
if (orig->owner != current->tid)
|
||||||
|
return -ENOCAP;
|
||||||
|
|
||||||
|
/* Check that it is destroyable */
|
||||||
|
if (!(cap_generic_perms(orig) & CAP_CHANGEABLE))
|
||||||
|
return -ENOCAP;
|
||||||
|
|
||||||
|
cap_find_destroy(cap->capid);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Splits a capability
|
* Splits a capability
|
||||||
*
|
*
|
||||||
@@ -374,6 +404,10 @@ int cap_split(struct capability *diff)
|
|||||||
if (orig->owner != current->tid)
|
if (orig->owner != current->tid)
|
||||||
return -ENOCAP;
|
return -ENOCAP;
|
||||||
|
|
||||||
|
/* Check owners are same for request validity */
|
||||||
|
if (orig->owner != diff->owner)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
/* Check that it is splitable */
|
/* Check that it is splitable */
|
||||||
if (!(orig->access & CAP_CHANGEABLE))
|
if (!(orig->access & CAP_CHANGEABLE))
|
||||||
return -ENOCAP;
|
return -ENOCAP;
|
||||||
@@ -427,6 +461,9 @@ int cap_split(struct capability *diff)
|
|||||||
} else if (new->size)
|
} else if (new->size)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
/* No used diff allowed for request validity */
|
||||||
|
if (diff->used)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
/* Check range usage but don't split if requested */
|
/* Check range usage but don't split if requested */
|
||||||
if (orig->start || orig->end) {
|
if (orig->start || orig->end) {
|
||||||
@@ -439,8 +476,6 @@ int cap_split(struct capability *diff)
|
|||||||
} else if (new->start || new->end)
|
} else if (new->start || new->end)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Copy other fields */
|
/* Copy other fields */
|
||||||
new->type = orig->type;
|
new->type = orig->type;
|
||||||
new->resid = orig->resid;
|
new->resid = orig->resid;
|
||||||
@@ -557,14 +592,24 @@ int sys_capability_control(unsigned int req, unsigned int flags,
|
|||||||
err = cap_share(capid, flags);
|
err = cap_share(capid, flags);
|
||||||
break;
|
break;
|
||||||
case CAP_CONTROL_GRANT:
|
case CAP_CONTROL_GRANT:
|
||||||
err = cap_grant(flags, capid, target);
|
if ((err = check_access((unsigned long)userbuf,
|
||||||
|
sizeof(struct capability),
|
||||||
|
MAP_USR_RW_FLAGS, 1)) < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
err = cap_grant((struct capability *)userbuf, flags);
|
||||||
break;
|
break;
|
||||||
case CAP_CONTROL_SPLIT:
|
case CAP_CONTROL_SPLIT:
|
||||||
|
if ((err = check_access((unsigned long)userbuf,
|
||||||
|
sizeof(struct capability),
|
||||||
|
MAP_USR_RW_FLAGS, 1)) < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
err = cap_split((struct capability *)userbuf);
|
err = cap_split((struct capability *)userbuf);
|
||||||
break;
|
break;
|
||||||
case CAP_CONTROL_REPLICATE:
|
case CAP_CONTROL_REPLICATE:
|
||||||
if ((err = check_access((unsigned long)userbuf,
|
if ((err = check_access((unsigned long)userbuf,
|
||||||
sizeof(int),
|
sizeof(struct capability),
|
||||||
MAP_USR_RW_FLAGS, 1)) < 0)
|
MAP_USR_RW_FLAGS, 1)) < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
@@ -572,12 +617,21 @@ int sys_capability_control(unsigned int req, unsigned int flags,
|
|||||||
break;
|
break;
|
||||||
case CAP_CONTROL_DEDUCE:
|
case CAP_CONTROL_DEDUCE:
|
||||||
if ((err = check_access((unsigned long)userbuf,
|
if ((err = check_access((unsigned long)userbuf,
|
||||||
sizeof(int),
|
sizeof(struct capability),
|
||||||
MAP_USR_RW_FLAGS, 1)) < 0)
|
MAP_USR_RW_FLAGS, 1)) < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
err = cap_deduce((struct capability *)userbuf);
|
err = cap_deduce((struct capability *)userbuf);
|
||||||
break;
|
break;
|
||||||
|
case CAP_CONTROL_DESTROY:
|
||||||
|
if ((err = check_access((unsigned long)userbuf,
|
||||||
|
sizeof(struct capability),
|
||||||
|
MAP_USR_RW_FLAGS, 1)) < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
err = cap_destroy((struct capability *)userbuf);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* Invalid request id */
|
/* Invalid request id */
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|||||||
@@ -154,6 +154,43 @@ struct capability *cap_find_byid(l4id_t capid)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO: Instead of destroying, use cap_find_byid match function's
|
||||||
|
* match_args to pass a pointer to the capability list, so the
|
||||||
|
* caller may destroy it
|
||||||
|
*/
|
||||||
|
int cap_find_destroy(l4id_t capid)
|
||||||
|
{
|
||||||
|
struct capability *cap;
|
||||||
|
struct ktcb *task = current;
|
||||||
|
|
||||||
|
/* Search task's own list */
|
||||||
|
list_foreach_struct(cap, &task->cap_list.caps, list)
|
||||||
|
if (cap->capid == capid) {
|
||||||
|
cap_list_remove(cap, &task->cap_list);
|
||||||
|
free_capability(cap);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Search space list */
|
||||||
|
list_foreach_struct(cap, &task->space->cap_list.caps, list)
|
||||||
|
if (cap->capid == capid) {
|
||||||
|
cap_list_remove(cap, &task->space->cap_list);
|
||||||
|
free_capability(cap);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Search container list */
|
||||||
|
list_foreach_struct(cap, &task->container->cap_list.caps, list)
|
||||||
|
if (cap->capid == capid) {
|
||||||
|
cap_list_remove(cap, &task->container->cap_list);
|
||||||
|
free_capability(cap);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -EEXIST;
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct capability *(*cap_match_func_t) \
|
typedef struct capability *(*cap_match_func_t) \
|
||||||
(struct capability *cap, void *match_args);
|
(struct capability *cap, void *match_args);
|
||||||
|
|
||||||
@@ -273,6 +310,9 @@ cap_match_capctrl(struct capability *cap, void *args_ptr)
|
|||||||
if (req == CAP_CONTROL_DEDUCE)
|
if (req == CAP_CONTROL_DEDUCE)
|
||||||
if (!(cap->access & CAP_CAP_DEDUCE))
|
if (!(cap->access & CAP_CAP_DEDUCE))
|
||||||
return 0;
|
return 0;
|
||||||
|
if (req == CAP_CONTROL_DESTROY)
|
||||||
|
if (!(cap->access & CAP_CAP_DESTROY))
|
||||||
|
return 0;
|
||||||
|
|
||||||
/* Now check the usual restype/resid pair */
|
/* Now check the usual restype/resid pair */
|
||||||
switch (cap_rtype(cap)) {
|
switch (cap_rtype(cap)) {
|
||||||
|
|||||||
Reference in New Issue
Block a user