mirror of
https://github.com/drasko/codezero.git
synced 2026-07-13 02:44:13 +02:00
Substantially fixed cap_split() behaviour.
Need to fix ipc flags capability checking yet.
This commit is contained in:
@@ -103,6 +103,118 @@ void cap_list_print(struct cap_list *cap_list)
|
|||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define PAGER_TOTAL_MUTEX 5
|
||||||
|
int setup_children_mutex(int total_caps, struct cap_list *cap_list)
|
||||||
|
{
|
||||||
|
struct capability *diff_cap, *mutex_cap;
|
||||||
|
|
||||||
|
struct task_ids ids;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
l4_getid(&ids);
|
||||||
|
|
||||||
|
cap_list_print(cap_list);
|
||||||
|
|
||||||
|
/* Find out own mutex capability on our own container */
|
||||||
|
list_foreach_struct(mutex_cap, &cap_list->caps, list) {
|
||||||
|
if (cap_type(mutex_cap) == CAP_TYPE_QUANTITY &&
|
||||||
|
cap_rtype(mutex_cap) == CAP_RTYPE_MUTEXPOOL)
|
||||||
|
goto found;
|
||||||
|
}
|
||||||
|
printf("cont%d: %s: FATAL: Could not find ipc "
|
||||||
|
"capability to own container.\n",
|
||||||
|
__cid(ids.tid), __FUNCTION__);
|
||||||
|
BUG();
|
||||||
|
|
||||||
|
found:
|
||||||
|
/* Create a new capability */
|
||||||
|
BUG_ON(!(diff_cap = kzalloc(sizeof(*mutex_cap))));
|
||||||
|
|
||||||
|
/* Copy it over to new mutex cap buffer */
|
||||||
|
memcpy(diff_cap, mutex_cap, sizeof (*mutex_cap));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We would like to take some mutexes,
|
||||||
|
* and leave the rest to children.
|
||||||
|
*
|
||||||
|
* We set up a capability that we want
|
||||||
|
* to separate out from the original
|
||||||
|
*/
|
||||||
|
if (mutex_cap->size <= PAGER_TOTAL_MUTEX) {
|
||||||
|
printf("%s: FATAL: Can't reserve enough mutexes "
|
||||||
|
"for children. capid = %d, mutexes = %lu, "
|
||||||
|
"pager needs = %d\n", __FUNCTION__,
|
||||||
|
mutex_cap->capid, mutex_cap->size,
|
||||||
|
PAGER_TOTAL_MUTEX);
|
||||||
|
BUG();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reserve out some mutexes to self */
|
||||||
|
diff_cap->size = PAGER_TOTAL_MUTEX;
|
||||||
|
|
||||||
|
/* Split the mutex capability, passing the difference */
|
||||||
|
if ((err = l4_capability_control(CAP_CONTROL_SPLIT,
|
||||||
|
0, 0, 0, diff_cap)) < 0) {
|
||||||
|
printf("l4_capability_control() replication of "
|
||||||
|
"ipc capability failed.\n Could not "
|
||||||
|
"complete CAP_CONTROL_SPLIT request on cap (%d), "
|
||||||
|
"err = %d.\n", diff_cap->capid, err);
|
||||||
|
BUG();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The returned one is the given diff, but
|
||||||
|
* created as a new capability, add it to list
|
||||||
|
*/
|
||||||
|
cap_list_insert(diff_cap, cap_list);
|
||||||
|
cap_list_print(cap_list);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Share the remainder capability with our container.
|
||||||
|
*
|
||||||
|
* This effectively enables all threads/spaces in this container
|
||||||
|
* to use this pool of mutexes.
|
||||||
|
*/
|
||||||
|
if ((err = l4_capability_control(CAP_CONTROL_SHARE, CAP_SHARE_SINGLE,
|
||||||
|
mutex_cap->capid, 0, 0)) < 0) {
|
||||||
|
printf("l4_capability_control() sharing of "
|
||||||
|
"capabilities failed.\n Could not "
|
||||||
|
"complete CAP_CONTROL_SHARE request.\n");
|
||||||
|
BUG();
|
||||||
|
}
|
||||||
|
cap_list_print(cap_list);
|
||||||
|
|
||||||
|
/* Find mutex syscall operation capability on our own container */
|
||||||
|
list_foreach_struct(mutex_cap, &cap_list->caps, list) {
|
||||||
|
if (cap_type(mutex_cap) == CAP_TYPE_UMUTEX &&
|
||||||
|
cap_rtype(mutex_cap) == CAP_RTYPE_CONTAINER)
|
||||||
|
goto found2;
|
||||||
|
}
|
||||||
|
printf("cont%d: %s: FATAL: Could not find UMUTEX "
|
||||||
|
"capability to own container.\n",
|
||||||
|
__cid(ids.tid), __FUNCTION__);
|
||||||
|
BUG();
|
||||||
|
|
||||||
|
found2:
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Share it with our container.
|
||||||
|
*
|
||||||
|
* This effectively enables all threads/spaces in this container
|
||||||
|
* to use this pool of mutexes.
|
||||||
|
*/
|
||||||
|
if ((err = l4_capability_control(CAP_CONTROL_SHARE, CAP_SHARE_SINGLE,
|
||||||
|
mutex_cap->capid, 0, 0)) < 0) {
|
||||||
|
printf("l4_capability_control() sharing of "
|
||||||
|
"capabilities failed.\n Could not "
|
||||||
|
"complete CAP_CONTROL_SHARE request.\n");
|
||||||
|
BUG();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Replicate, deduce and grant to children the capability to
|
* Replicate, deduce and grant to children the capability to
|
||||||
* talk to us only.
|
* talk to us only.
|
||||||
@@ -115,7 +227,7 @@ void cap_list_print(struct cap_list *cap_list)
|
|||||||
* into a capability to only talk to our current space. Our space is a
|
* into a capability to only talk to our current space. Our space is a
|
||||||
* reduced target, since it is a subset contained in our container.
|
* reduced target, since it is a subset contained in our container.
|
||||||
*/
|
*/
|
||||||
int setup_children_caps(int total_caps, struct cap_list *cap_list)
|
int setup_children_ipc(int total_caps, struct cap_list *cap_list)
|
||||||
{
|
{
|
||||||
struct capability *ipc_cap, *cap;
|
struct capability *ipc_cap, *cap;
|
||||||
struct task_ids ids;
|
struct task_ids ids;
|
||||||
@@ -195,6 +307,13 @@ found:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int setup_children_caps(int total_caps, struct cap_list *cap_list)
|
||||||
|
{
|
||||||
|
setup_children_ipc(total_caps, cap_list);
|
||||||
|
setup_children_mutex(total_caps, cap_list);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Copy all init-memory allocated capabilities */
|
/* Copy all init-memory allocated capabilities */
|
||||||
void copy_boot_capabilities(int ncaps)
|
void copy_boot_capabilities(int ncaps)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#define __TASKNAME__ "test0"
|
#define __TASKNAME__ "test0"
|
||||||
|
|
||||||
//#define TEST_VERBOSE_PRINT
|
// #define TEST_VERBOSE_PRINT
|
||||||
#if defined (TEST_VERBOSE_PRINT)
|
#if defined (TEST_VERBOSE_PRINT)
|
||||||
#define test_printf(...) printf(__VA_ARGS__)
|
#define test_printf(...) printf(__VA_ARGS__)
|
||||||
#else
|
#else
|
||||||
|
|||||||
@@ -63,9 +63,12 @@ int main(int argc, char *argv[])
|
|||||||
user_mutex_test();
|
user_mutex_test();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
exectest(parent_of_all);
|
exectest(parent_of_all);
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
wait_pager(pagerid);
|
wait_pager(pagerid);
|
||||||
|
*/
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,9 +10,7 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <tests.h>
|
#include <tests.h>
|
||||||
#include <l4/api/capability.h>
|
#include <capability.h>
|
||||||
#include <l4/generic/cap-types.h>
|
|
||||||
#include <l4lib/capability.h>
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Full ipc test. Sends/receives full utcb, done with the pager.
|
* Full ipc test. Sends/receives full utcb, done with the pager.
|
||||||
@@ -48,26 +46,6 @@ void ipc_full_test(void)
|
|||||||
printf("FULL IPC TEST: -- FAILED --\n");
|
printf("FULL IPC TEST: -- FAILED --\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
int cap_request_pager(struct capability *cap)
|
|
||||||
{
|
|
||||||
int err;
|
|
||||||
|
|
||||||
write_mr(L4SYS_ARG0, (u32)cap);
|
|
||||||
|
|
||||||
if ((err = l4_sendrecv(pagerid, pagerid,
|
|
||||||
L4_REQUEST_CAPABILITY)) < 0) {
|
|
||||||
printf("%s: L4 IPC Error: %d.\n", __FUNCTION__, err);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if syscall itself was successful */
|
|
||||||
if ((err = l4_get_retval()) < 0) {
|
|
||||||
printf("%s: Error: %d\n", __FUNCTION__, err);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is an extended ipc test that is done between 2 tasks that fork.
|
* This is an extended ipc test that is done between 2 tasks that fork.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <tests.h>
|
#include <tests.h>
|
||||||
|
#include <capability.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This structure is placed at the head of shared memory.
|
* This structure is placed at the head of shared memory.
|
||||||
@@ -36,7 +37,9 @@ int user_mutex_test(void)
|
|||||||
{
|
{
|
||||||
pid_t child, parent;
|
pid_t child, parent;
|
||||||
int map_size = PAGE_SIZE;
|
int map_size = PAGE_SIZE;
|
||||||
|
struct capability cap;
|
||||||
void *base;
|
void *base;
|
||||||
|
int err;
|
||||||
|
|
||||||
/* Get parent pid */
|
/* Get parent pid */
|
||||||
parent = getpid();
|
parent = getpid();
|
||||||
@@ -73,6 +76,27 @@ int user_mutex_test(void)
|
|||||||
else
|
else
|
||||||
test_printf("Child %d running.\n", getpid());
|
test_printf("Child %d running.\n", getpid());
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Request capability to ipc to each other from pager
|
||||||
|
* (Actually only the sender needs it)
|
||||||
|
*/
|
||||||
|
memset(&cap, 0, sizeof(cap));
|
||||||
|
if (child) {
|
||||||
|
cap.owner = parent;
|
||||||
|
cap.resid = child;
|
||||||
|
} else {
|
||||||
|
cap.owner = getpid();
|
||||||
|
cap.resid = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
cap.type = CAP_TYPE_IPC | CAP_RTYPE_THREAD;
|
||||||
|
cap.access = CAP_IPC_EXTENDED | CAP_IPC_SEND | CAP_IPC_RECV;
|
||||||
|
if ((err = cap_request_pager(&cap)) < 0) {
|
||||||
|
printf("Ipc capability request failed. "
|
||||||
|
"err = %d\n", err);
|
||||||
|
goto out_err;
|
||||||
|
}
|
||||||
|
|
||||||
/* Child locks and produces */
|
/* Child locks and produces */
|
||||||
if (child == 0) {
|
if (child == 0) {
|
||||||
|
|
||||||
@@ -107,7 +131,11 @@ int user_mutex_test(void)
|
|||||||
|
|
||||||
}
|
}
|
||||||
/* Sync with the parent */
|
/* Sync with the parent */
|
||||||
l4_send(parent, L4_IPC_TAG_SYNC);
|
if ((err = l4_send_full(parent, L4_IPC_TAG_SYNC)) < 0) {
|
||||||
|
printf("Error: l4_send() failed with %d\n", err);
|
||||||
|
goto out_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Parent locks and consumes */
|
/* Parent locks and consumes */
|
||||||
} else {
|
} else {
|
||||||
@@ -141,7 +169,10 @@ int user_mutex_test(void)
|
|||||||
l4_thread_switch(0);
|
l4_thread_switch(0);
|
||||||
}
|
}
|
||||||
/* Sync with the child */
|
/* Sync with the child */
|
||||||
l4_receive(child);
|
if ((err = l4_receive_full(child)) < 0) {
|
||||||
|
printf("Error: l4_receive() failed with %d\n", err);
|
||||||
|
goto out_err;
|
||||||
|
}
|
||||||
|
|
||||||
// test_printf("Parent checking validity of value.\n");
|
// test_printf("Parent checking validity of value.\n");
|
||||||
if (shared_page->shared_var != 0)
|
if (shared_page->shared_var != 0)
|
||||||
|
|||||||
@@ -25,6 +25,11 @@
|
|||||||
#define CAP_GRANT_ALL 0x00000002
|
#define CAP_GRANT_ALL 0x00000002
|
||||||
#define CAP_GRANT_IMMUTABLE 0x00000004
|
#define CAP_GRANT_IMMUTABLE 0x00000004
|
||||||
|
|
||||||
|
#define CAP_SPLIT_MASK 0x0000000F
|
||||||
|
#define CAP_SPLIT_SIZE 0x00000001
|
||||||
|
#define CAP_SPLIT_ACCESS 0x00000002
|
||||||
|
#define CAP_SPLIT_RANGE 0x00000003 /* Returns -EPERM */
|
||||||
|
|
||||||
/* Task's primary capability list */
|
/* Task's primary capability list */
|
||||||
#define TASK_CAP_LIST(task) \
|
#define TASK_CAP_LIST(task) \
|
||||||
(&((task)->space->cap_list))
|
(&((task)->space->cap_list))
|
||||||
|
|||||||
140
src/api/cap.c
140
src/api/cap.c
@@ -370,6 +370,16 @@ int cap_destroy(struct capability *cap)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int cap_has_size(struct capability *c)
|
||||||
|
{
|
||||||
|
return c->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int cap_has_range(struct capability *c)
|
||||||
|
{
|
||||||
|
return c->start && c->end;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Splits a capability
|
* Splits a capability
|
||||||
*
|
*
|
||||||
@@ -386,9 +396,10 @@ int cap_destroy(struct capability *cap)
|
|||||||
* orig = orig - diff;
|
* orig = orig - diff;
|
||||||
* new = diff;
|
* new = diff;
|
||||||
*/
|
*/
|
||||||
int cap_split(struct capability *diff)
|
int cap_split(struct capability *diff, unsigned int flags)
|
||||||
{
|
{
|
||||||
struct capability *orig, *new;
|
struct capability *orig, *new;
|
||||||
|
int ret;
|
||||||
|
|
||||||
/* Find original capability */
|
/* Find original capability */
|
||||||
if (!(orig = cap_find_byid(diff->capid)))
|
if (!(orig = cap_find_byid(diff->capid)))
|
||||||
@@ -404,7 +415,7 @@ 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 */
|
/* Check owners are same */
|
||||||
if (orig->owner != diff->owner)
|
if (orig->owner != diff->owner)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
@@ -417,17 +428,26 @@ int cap_split(struct capability *diff)
|
|||||||
return -ENOCAP;
|
return -ENOCAP;
|
||||||
|
|
||||||
/* Check access bits usage and split */
|
/* Check access bits usage and split */
|
||||||
if (orig->access) {
|
if (flags & CAP_SPLIT_ACCESS) {
|
||||||
|
/* Access bits must never be redundant */
|
||||||
|
BUG_ON(!orig->access);
|
||||||
|
|
||||||
/* Split one can't have more bits than original */
|
/* Split one can't have more bits than original */
|
||||||
if ((orig->access & diff->access) != diff->access) {
|
if ((orig->access & diff->access) != diff->access) {
|
||||||
free_capability(new);
|
ret = -EINVAL;
|
||||||
return -EINVAL;
|
goto out_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Split one cannot make original redundant */
|
/* Split one cannot make original redundant */
|
||||||
if ((orig->access & ~diff->access) == 0) {
|
if ((orig->access & ~diff->access) == 0) {
|
||||||
free_capability(new);
|
ret = -EINVAL;
|
||||||
return -EINVAL;
|
goto out_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Split one cannot be redundant itself */
|
||||||
|
if (!diff->access) {
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto out_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Subtract given access permissions */
|
/* Subtract given access permissions */
|
||||||
@@ -435,46 +455,88 @@ int cap_split(struct capability *diff)
|
|||||||
|
|
||||||
/* Assign given perms to new capability */
|
/* Assign given perms to new capability */
|
||||||
new->access = diff->access;
|
new->access = diff->access;
|
||||||
} else if (new->access)
|
} else {
|
||||||
return -EINVAL;
|
/* Can't split only by access bits alone */
|
||||||
|
if (!cap_has_size(orig) &&
|
||||||
|
!cap_has_range(orig)) {
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto out_err;
|
||||||
|
}
|
||||||
|
/* If no split, then they are identical */
|
||||||
|
new->access = orig->access;
|
||||||
|
|
||||||
|
/* Diff must also reflect orig by convention */
|
||||||
|
if (diff->access != orig->access) {
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto out_err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If cap has size, split by size is compulsory */
|
||||||
|
if (cap_type(orig) == CAP_TYPE_QUANTITY) {
|
||||||
|
BUG_ON(!cap_has_size(orig));
|
||||||
|
|
||||||
/* Check size usage and split */
|
|
||||||
if (orig->size) {
|
|
||||||
/*
|
/*
|
||||||
* Split one can't have more,
|
* Split one can't have more,
|
||||||
* or make original redundant
|
* or make original redundant
|
||||||
*/
|
*/
|
||||||
if (diff->size >= orig->size) {
|
if (diff->size >= orig->size) {
|
||||||
free_capability(new);
|
ret = -EINVAL;
|
||||||
return -EINVAL;
|
goto out_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Split one can't be redundant itself */
|
||||||
|
if (!diff->size) {
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto out_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Split one must be clean i.e. all unused */
|
/* Split one must be clean i.e. all unused */
|
||||||
if (orig->size - orig->used < diff->size) {
|
if (orig->size - orig->used < diff->size) {
|
||||||
free_capability(new);
|
ret = -EPERM;
|
||||||
return -EPERM;
|
goto out_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
orig->size -= diff->size;
|
orig->size -= diff->size;
|
||||||
new->size = diff->size;
|
new->size = diff->size;
|
||||||
new->used = 0;
|
new->used = 0;
|
||||||
} else if (new->size)
|
} else {
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
/* No used diff allowed for request validity */
|
/* Diff must also reflect orig by convention */
|
||||||
if (diff->used)
|
if (diff->size != orig->size) {
|
||||||
return -EINVAL;
|
ret = -EINVAL;
|
||||||
|
goto out_err;
|
||||||
/* Check range usage but don't split if requested */
|
|
||||||
if (orig->start || orig->end) {
|
|
||||||
/* Range-like permissions can't be deduced */
|
|
||||||
if (orig->start != new->start ||
|
|
||||||
orig->end != new->end) {
|
|
||||||
free_capability(new);
|
|
||||||
return -EPERM;
|
|
||||||
}
|
}
|
||||||
} else if (new->start || new->end)
|
|
||||||
return -EINVAL;
|
/* If no split, then they are identical */
|
||||||
|
new->size = orig->size;
|
||||||
|
new->used = orig->used;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & CAP_SPLIT_RANGE) {
|
||||||
|
/* They must either be both one or both zero */
|
||||||
|
BUG_ON(!!orig->start ^ !!orig->end);
|
||||||
|
|
||||||
|
/* If orig doesn't have a range, return invalid */
|
||||||
|
if (!orig->start && !orig->end) {
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto out_err;
|
||||||
|
} else {
|
||||||
|
/* Orig has a range but diff doesn't */
|
||||||
|
if (!diff->start || !diff->end) {
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto out_err;
|
||||||
|
}
|
||||||
|
/* Both valid, but we don't permit range split */
|
||||||
|
ret = -EPERM;
|
||||||
|
goto out_err;
|
||||||
|
}
|
||||||
|
/* If no split, then they are identical */
|
||||||
|
} else {
|
||||||
|
new->start = orig->start;
|
||||||
|
new->end = orig->end;
|
||||||
|
}
|
||||||
|
|
||||||
/* Copy other fields */
|
/* Copy other fields */
|
||||||
new->type = orig->type;
|
new->type = orig->type;
|
||||||
@@ -484,7 +546,7 @@ int cap_split(struct capability *diff)
|
|||||||
/* Add the new capability to the most private list */
|
/* Add the new capability to the most private list */
|
||||||
cap_list_insert(new, TASK_CAP_LIST(current));
|
cap_list_insert(new, TASK_CAP_LIST(current));
|
||||||
|
|
||||||
/* Copy the new one to diff for userspace */
|
/* Check fields that must be identical */
|
||||||
BUG_ON(new->resid != diff->resid);
|
BUG_ON(new->resid != diff->resid);
|
||||||
BUG_ON(new->owner != diff->owner);
|
BUG_ON(new->owner != diff->owner);
|
||||||
BUG_ON(new->type != diff->type);
|
BUG_ON(new->type != diff->type);
|
||||||
@@ -492,10 +554,15 @@ int cap_split(struct capability *diff)
|
|||||||
BUG_ON(new->start != diff->start);
|
BUG_ON(new->start != diff->start);
|
||||||
BUG_ON(new->end != diff->end);
|
BUG_ON(new->end != diff->end);
|
||||||
BUG_ON(new->size != diff->size);
|
BUG_ON(new->size != diff->size);
|
||||||
BUG_ON(new->used != diff->used);
|
|
||||||
diff->capid = new->capid;
|
|
||||||
|
|
||||||
|
/* Copy capid, and used field that may not be the same */
|
||||||
|
diff->capid = new->capid;
|
||||||
|
diff->used = new->used;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
out_err:
|
||||||
|
free_capability(new);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -569,6 +636,11 @@ int sys_capability_control(unsigned int req, unsigned int flags,
|
|||||||
if ((err = cap_cap_check(current, req, flags)) < 0)
|
if ((err = cap_cap_check(current, req, flags)) < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FIXME: Create a case statement to collect check_access
|
||||||
|
* calls to one place.
|
||||||
|
*/
|
||||||
|
|
||||||
switch(req) {
|
switch(req) {
|
||||||
case CAP_CONTROL_NCAPS:
|
case CAP_CONTROL_NCAPS:
|
||||||
/* Return number of caps */
|
/* Return number of caps */
|
||||||
@@ -605,7 +677,7 @@ int sys_capability_control(unsigned int req, unsigned int flags,
|
|||||||
MAP_USR_RW_FLAGS, 1)) < 0)
|
MAP_USR_RW_FLAGS, 1)) < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
err = cap_split((struct capability *)userbuf);
|
err = cap_split((struct capability *)userbuf, flags);
|
||||||
break;
|
break;
|
||||||
case CAP_CONTROL_REPLICATE:
|
case CAP_CONTROL_REPLICATE:
|
||||||
if ((err = check_access((unsigned long)userbuf,
|
if ((err = check_access((unsigned long)userbuf,
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
#include INC_SUBARCH(mm.h)
|
#include INC_SUBARCH(mm.h)
|
||||||
|
|
||||||
/* Abort debugging conditions */
|
/* Abort debugging conditions */
|
||||||
//#define DEBUG_ABORTS
|
// #define DEBUG_ABORTS
|
||||||
#if defined (DEBUG_ABORTS)
|
#if defined (DEBUG_ABORTS)
|
||||||
#define dbg_abort(...) dprintk(__VA_ARGS__)
|
#define dbg_abort(...) dprintk(__VA_ARGS__)
|
||||||
#else
|
#else
|
||||||
|
|||||||
Reference in New Issue
Block a user