* [PATCH 3/4] KEYS: Allow the callout data to be passed as a blob rather than a string
2008-02-08 16:04 [PATCH 1/4] KEYS: Increase the payload size when instantiating a key David Howells
2008-02-08 16:04 ` [PATCH 2/4] KEYS: Check starting keyring as part of search David Howells
@ 2008-02-08 16:04 ` David Howells
2008-02-08 16:04 ` [PATCH 4/4] KEYS: Add keyctl function to get a security label David Howells
2 siblings, 0 replies; 8+ messages in thread
From: David Howells @ 2008-02-08 16:04 UTC (permalink / raw)
To: torvalds; +Cc: linux-kernel, dhowells
Allow the callout data to be passed as a blob rather than a string for internal
kernel services that call any request_key_*() interface other than
request_key(). request_key() itself still takes a NUL-terminated string.
The functions that change are:
request_key_with_auxdata()
request_key_async()
request_key_async_with_auxdata()
Signed-off-by: David Howells <dhowells@redhat.com>
---
Documentation/keys-request-key.txt | 11 +++++---
Documentation/keys.txt | 14 +++++++---
include/linux/key.h | 9 ++++---
security/keys/internal.h | 9 ++++---
security/keys/keyctl.c | 7 ++++-
security/keys/request_key.c | 49 ++++++++++++++++++++++--------------
security/keys/request_key_auth.c | 12 +++++----
7 files changed, 70 insertions(+), 41 deletions(-)
diff --git a/Documentation/keys-request-key.txt b/Documentation/keys-request-key.txt
index 266955d..09b55e4 100644
--- a/Documentation/keys-request-key.txt
+++ b/Documentation/keys-request-key.txt
@@ -11,26 +11,29 @@ request_key*():
struct key *request_key(const struct key_type *type,
const char *description,
- const char *callout_string);
+ const char *callout_info);
or:
struct key *request_key_with_auxdata(const struct key_type *type,
const char *description,
- const char *callout_string,
+ const char *callout_info,
+ size_t callout_len,
void *aux);
or:
struct key *request_key_async(const struct key_type *type,
const char *description,
- const char *callout_string);
+ const char *callout_info,
+ size_t callout_len);
or:
struct key *request_key_async_with_auxdata(const struct key_type *type,
const char *description,
- const char *callout_string,
+ const char *callout_info,
+ size_t callout_len,
void *aux);
Or by userspace invoking the request_key system call:
diff --git a/Documentation/keys.txt b/Documentation/keys.txt
index 51652d3..b82d38d 100644
--- a/Documentation/keys.txt
+++ b/Documentation/keys.txt
@@ -771,7 +771,7 @@ payload contents" for more information.
struct key *request_key(const struct key_type *type,
const char *description,
- const char *callout_string);
+ const char *callout_info);
This is used to request a key or keyring with a description that matches
the description specified according to the key type's match function. This
@@ -793,24 +793,28 @@ payload contents" for more information.
struct key *request_key_with_auxdata(const struct key_type *type,
const char *description,
- const char *callout_string,
+ const void *callout_info,
+ size_t callout_len,
void *aux);
This is identical to request_key(), except that the auxiliary data is
- passed to the key_type->request_key() op if it exists.
+ passed to the key_type->request_key() op if it exists, and the callout_info
+ is a blob of length callout_len, if given (the length may be 0).
(*) A key can be requested asynchronously by calling one of:
struct key *request_key_async(const struct key_type *type,
const char *description,
- const char *callout_string);
+ const void *callout_info,
+ size_t callout_len);
or:
struct key *request_key_async_with_auxdata(const struct key_type *type,
const char *description,
- const char *callout_string,
+ const char *callout_info,
+ size_t callout_len,
void *aux);
which are asynchronous equivalents of request_key() and
diff --git a/include/linux/key.h b/include/linux/key.h
index a70b8a8..163f864 100644
--- a/include/linux/key.h
+++ b/include/linux/key.h
@@ -208,16 +208,19 @@ extern struct key *request_key(struct key_type *type,
extern struct key *request_key_with_auxdata(struct key_type *type,
const char *description,
- const char *callout_info,
+ const void *callout_info,
+ size_t callout_len,
void *aux);
extern struct key *request_key_async(struct key_type *type,
const char *description,
- const char *callout_info);
+ const void *callout_info,
+ size_t callout_len);
extern struct key *request_key_async_with_auxdata(struct key_type *type,
const char *description,
- const char *callout_info,
+ const void *callout_info,
+ size_t callout_len,
void *aux);
extern int wait_for_key_construction(struct key *key, bool intr);
diff --git a/security/keys/internal.h b/security/keys/internal.h
index d36d693..f004835 100644
--- a/security/keys/internal.h
+++ b/security/keys/internal.h
@@ -109,7 +109,8 @@ extern int install_process_keyring(struct task_struct *tsk);
extern struct key *request_key_and_link(struct key_type *type,
const char *description,
- const char *callout_info,
+ const void *callout_info,
+ size_t callout_len,
void *aux,
struct key *dest_keyring,
unsigned long flags);
@@ -120,13 +121,15 @@ extern struct key *request_key_and_link(struct key_type *type,
struct request_key_auth {
struct key *target_key;
struct task_struct *context;
- char *callout_info;
+ void *callout_info;
+ size_t callout_len;
pid_t pid;
};
extern struct key_type key_type_request_key_auth;
extern struct key *request_key_auth_new(struct key *target,
- const char *callout_info);
+ const void *callout_info,
+ size_t callout_len);
extern struct key *key_get_instantiation_authkey(key_serial_t target_id);
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index 8ec8432..1698bf9 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -152,6 +152,7 @@ asmlinkage long sys_request_key(const char __user *_type,
struct key_type *ktype;
struct key *key;
key_ref_t dest_ref;
+ size_t callout_len;
char type[32], *description, *callout_info;
long ret;
@@ -169,12 +170,14 @@ asmlinkage long sys_request_key(const char __user *_type,
/* pull the callout info into kernel space */
callout_info = NULL;
+ callout_len = 0;
if (_callout_info) {
callout_info = strndup_user(_callout_info, PAGE_SIZE);
if (IS_ERR(callout_info)) {
ret = PTR_ERR(callout_info);
goto error2;
}
+ callout_len = strlen(callout_info);
}
/* get the destination keyring if specified */
@@ -195,8 +198,8 @@ asmlinkage long sys_request_key(const char __user *_type,
}
/* do the search */
- key = request_key_and_link(ktype, description, callout_info, NULL,
- key_ref_to_ptr(dest_ref),
+ key = request_key_and_link(ktype, description, callout_info,
+ callout_len, NULL, key_ref_to_ptr(dest_ref),
KEY_ALLOC_IN_QUOTA);
if (IS_ERR(key)) {
ret = PTR_ERR(key);
diff --git a/security/keys/request_key.c b/security/keys/request_key.c
index 5ecc505..a3f94c6 100644
--- a/security/keys/request_key.c
+++ b/security/keys/request_key.c
@@ -161,21 +161,22 @@ error_alloc:
* call out to userspace for key construction
* - we ignore program failure and go on key status instead
*/
-static int construct_key(struct key *key, const char *callout_info, void *aux)
+static int construct_key(struct key *key, const void *callout_info,
+ size_t callout_len, void *aux)
{
struct key_construction *cons;
request_key_actor_t actor;
struct key *authkey;
int ret;
- kenter("%d,%s,%p", key->serial, callout_info, aux);
+ kenter("%d,%p,%zu,%p", key->serial, callout_info, callout_len, aux);
cons = kmalloc(sizeof(*cons), GFP_KERNEL);
if (!cons)
return -ENOMEM;
/* allocate an authorisation key */
- authkey = request_key_auth_new(key, callout_info);
+ authkey = request_key_auth_new(key, callout_info, callout_len);
if (IS_ERR(authkey)) {
kfree(cons);
ret = PTR_ERR(authkey);
@@ -331,6 +332,7 @@ alloc_failed:
static struct key *construct_key_and_link(struct key_type *type,
const char *description,
const char *callout_info,
+ size_t callout_len,
void *aux,
struct key *dest_keyring,
unsigned long flags)
@@ -348,7 +350,7 @@ static struct key *construct_key_and_link(struct key_type *type,
key_user_put(user);
if (ret == 0) {
- ret = construct_key(key, callout_info, aux);
+ ret = construct_key(key, callout_info, callout_len, aux);
if (ret < 0)
goto construction_failed;
}
@@ -370,7 +372,8 @@ construction_failed:
*/
struct key *request_key_and_link(struct key_type *type,
const char *description,
- const char *callout_info,
+ const void *callout_info,
+ size_t callout_len,
void *aux,
struct key *dest_keyring,
unsigned long flags)
@@ -378,8 +381,8 @@ struct key *request_key_and_link(struct key_type *type,
struct key *key;
key_ref_t key_ref;
- kenter("%s,%s,%s,%p,%p,%lx",
- type->name, description, callout_info, aux,
+ kenter("%s,%s,%p,%zu,%p,%p,%lx",
+ type->name, description, callout_info, callout_len, aux,
dest_keyring, flags);
/* search all the process keyrings for a key */
@@ -398,7 +401,8 @@ struct key *request_key_and_link(struct key_type *type,
goto error;
key = construct_key_and_link(type, description, callout_info,
- aux, dest_keyring, flags);
+ callout_len, aux, dest_keyring,
+ flags);
}
error:
@@ -434,10 +438,13 @@ struct key *request_key(struct key_type *type,
const char *callout_info)
{
struct key *key;
+ size_t callout_len = 0;
int ret;
- key = request_key_and_link(type, description, callout_info, NULL,
- NULL, KEY_ALLOC_IN_QUOTA);
+ if (callout_info)
+ callout_len = strlen(callout_info);
+ key = request_key_and_link(type, description, callout_info, callout_len,
+ NULL, NULL, KEY_ALLOC_IN_QUOTA);
if (!IS_ERR(key)) {
ret = wait_for_key_construction(key, false);
if (ret < 0) {
@@ -458,14 +465,15 @@ EXPORT_SYMBOL(request_key);
*/
struct key *request_key_with_auxdata(struct key_type *type,
const char *description,
- const char *callout_info,
+ const void *callout_info,
+ size_t callout_len,
void *aux)
{
struct key *key;
int ret;
- key = request_key_and_link(type, description, callout_info, aux,
- NULL, KEY_ALLOC_IN_QUOTA);
+ key = request_key_and_link(type, description, callout_info, callout_len,
+ aux, NULL, KEY_ALLOC_IN_QUOTA);
if (!IS_ERR(key)) {
ret = wait_for_key_construction(key, false);
if (ret < 0) {
@@ -485,10 +493,12 @@ EXPORT_SYMBOL(request_key_with_auxdata);
*/
struct key *request_key_async(struct key_type *type,
const char *description,
- const char *callout_info)
+ const void *callout_info,
+ size_t callout_len)
{
- return request_key_and_link(type, description, callout_info, NULL,
- NULL, KEY_ALLOC_IN_QUOTA);
+ return request_key_and_link(type, description, callout_info,
+ callout_len, NULL, NULL,
+ KEY_ALLOC_IN_QUOTA);
}
EXPORT_SYMBOL(request_key_async);
@@ -500,10 +510,11 @@ EXPORT_SYMBOL(request_key_async);
*/
struct key *request_key_async_with_auxdata(struct key_type *type,
const char *description,
- const char *callout_info,
+ const void *callout_info,
+ size_t callout_len,
void *aux)
{
- return request_key_and_link(type, description, callout_info, aux,
- NULL, KEY_ALLOC_IN_QUOTA);
+ return request_key_and_link(type, description, callout_info,
+ callout_len, aux, NULL, KEY_ALLOC_IN_QUOTA);
}
EXPORT_SYMBOL(request_key_async_with_auxdata);
diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c
index e42b525..c615d47 100644
--- a/security/keys/request_key_auth.c
+++ b/security/keys/request_key_auth.c
@@ -61,7 +61,7 @@ static void request_key_auth_describe(const struct key *key,
seq_puts(m, "key:");
seq_puts(m, key->description);
- seq_printf(m, " pid:%d ci:%zu", rka->pid, strlen(rka->callout_info));
+ seq_printf(m, " pid:%d ci:%zu", rka->pid, rka->callout_len);
} /* end request_key_auth_describe() */
@@ -77,7 +77,7 @@ static long request_key_auth_read(const struct key *key,
size_t datalen;
long ret;
- datalen = strlen(rka->callout_info);
+ datalen = rka->callout_len;
ret = datalen;
/* we can return the data as is */
@@ -137,7 +137,8 @@ static void request_key_auth_destroy(struct key *key)
* create an authorisation token for /sbin/request-key or whoever to gain
* access to the caller's security data
*/
-struct key *request_key_auth_new(struct key *target, const char *callout_info)
+struct key *request_key_auth_new(struct key *target, const void *callout_info,
+ size_t callout_len)
{
struct request_key_auth *rka, *irka;
struct key *authkey = NULL;
@@ -152,7 +153,7 @@ struct key *request_key_auth_new(struct key *target, const char *callout_info)
kleave(" = -ENOMEM");
return ERR_PTR(-ENOMEM);
}
- rka->callout_info = kmalloc(strlen(callout_info) + 1, GFP_KERNEL);
+ rka->callout_info = kmalloc(callout_len, GFP_KERNEL);
if (!rka->callout_info) {
kleave(" = -ENOMEM");
kfree(rka);
@@ -186,7 +187,8 @@ struct key *request_key_auth_new(struct key *target, const char *callout_info)
}
rka->target_key = key_get(target);
- strcpy(rka->callout_info, callout_info);
+ memcpy(rka->callout_info, callout_info, callout_len);
+ rka->callout_len = callout_len;
/* allocate the auth key */
sprintf(desc, "%x", target->serial);
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH 4/4] KEYS: Add keyctl function to get a security label
2008-02-08 16:04 [PATCH 1/4] KEYS: Increase the payload size when instantiating a key David Howells
2008-02-08 16:04 ` [PATCH 2/4] KEYS: Check starting keyring as part of search David Howells
2008-02-08 16:04 ` [PATCH 3/4] KEYS: Allow the callout data to be passed as a blob rather than a string David Howells
@ 2008-02-08 16:04 ` David Howells
2008-02-12 23:51 ` Andrew Morton
2 siblings, 1 reply; 8+ messages in thread
From: David Howells @ 2008-02-08 16:04 UTC (permalink / raw)
To: torvalds; +Cc: linux-kernel, dhowells
Add a keyctl() function to get the security label of a key.
The following is added to Documentation/keys.txt:
(*) Get the LSM security context attached to a key.
long keyctl(KEYCTL_GET_SECURITY, key_serial_t key, char *buffer,
size_t buflen)
This function returns a string that represents the LSM security context
attached to a key in the buffer provided.
Unless there's an error, it always returns the amount of data it could
produce, even if that's too big for the buffer, but it won't copy more
than requested to userspace. If the buffer pointer is NULL then no copy
will take place.
A NUL character is included at the end of the string if the buffer is
sufficiently big. This is included in the returned count. If no LSM is
in force then an empty string will be returned.
A process must have view permission on the key for this function to be
successful.
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
---
Documentation/keys.txt | 21 +++++++++++++++
include/linux/keyctl.h | 1 +
include/linux/security.h | 20 +++++++++++++-
security/dummy.c | 8 ++++++
security/keys/compat.c | 3 ++
security/keys/keyctl.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++
security/security.c | 5 +++
security/selinux/hooks.c | 21 +++++++++++++--
8 files changed, 141 insertions(+), 4 deletions(-)
diff --git a/Documentation/keys.txt b/Documentation/keys.txt
index b82d38d..be424b0 100644
--- a/Documentation/keys.txt
+++ b/Documentation/keys.txt
@@ -711,6 +711,27 @@ The keyctl syscall functions are:
The assumed authoritative key is inherited across fork and exec.
+ (*) Get the LSM security context attached to a key.
+
+ long keyctl(KEYCTL_GET_SECURITY, key_serial_t key, char *buffer,
+ size_t buflen)
+
+ This function returns a string that represents the LSM security context
+ attached to a key in the buffer provided.
+
+ Unless there's an error, it always returns the amount of data it could
+ produce, even if that's too big for the buffer, but it won't copy more
+ than requested to userspace. If the buffer pointer is NULL then no copy
+ will take place.
+
+ A NUL character is included at the end of the string if the buffer is
+ sufficiently big. This is included in the returned count. If no LSM is
+ in force then an empty string will be returned.
+
+ A process must have view permission on the key for this function to be
+ successful.
+
+
===============
KERNEL SERVICES
===============
diff --git a/include/linux/keyctl.h b/include/linux/keyctl.h
index 3365945..656ee6b 100644
--- a/include/linux/keyctl.h
+++ b/include/linux/keyctl.h
@@ -49,5 +49,6 @@
#define KEYCTL_SET_REQKEY_KEYRING 14 /* set default request-key keyring */
#define KEYCTL_SET_TIMEOUT 15 /* set key timeout */
#define KEYCTL_ASSUME_AUTHORITY 16 /* assume request_key() authorisation */
+#define KEYCTL_GET_SECURITY 17 /* get key security label */
#endif /* _LINUX_KEYCTL_H */
diff --git a/include/linux/security.h b/include/linux/security.h
index fe52cde..a33fd03 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -970,6 +970,17 @@ struct request_sock;
* @perm describes the combination of permissions required of this key.
* Return 1 if permission granted, 0 if permission denied and -ve it the
* normal permissions model should be effected.
+ * @key_getsecurity:
+ * Get a textual representation of the security context attached to a key
+ * for the purposes of honouring KEYCTL_GETSECURITY. This function
+ * allocates the storage for the NUL-terminated string and the caller
+ * should free it.
+ * @key points to the key to be queried.
+ * @_buffer points to a pointer that should be set to point to the
+ * resulting string (if no label or an error occurs).
+ * Return the length of the string (including terminating NUL) or -ve if
+ * an error.
+ * May also return 0 (and a NULL buffer pointer) if there is no label.
*
* Security hooks affecting all System V IPC operations.
*
@@ -1459,7 +1470,7 @@ struct security_operations {
int (*key_permission)(key_ref_t key_ref,
struct task_struct *context,
key_perm_t perm);
-
+ int (*key_getsecurity)(struct key *key, char **_buffer);
#endif /* CONFIG_KEYS */
};
@@ -2600,6 +2611,7 @@ int security_key_alloc(struct key *key, struct task_struct *tsk, unsigned long f
void security_key_free(struct key *key);
int security_key_permission(key_ref_t key_ref,
struct task_struct *context, key_perm_t perm);
+int security_key_getsecurity(struct key *key, char **_buffer);
#else
@@ -2621,6 +2633,12 @@ static inline int security_key_permission(key_ref_t key_ref,
return 0;
}
+static inline int security_key_getsecurity(struct key *key, char **_buffer)
+{
+ *_buffer = NULL;
+ return 0;
+}
+
#endif
#endif /* CONFIG_KEYS */
diff --git a/security/dummy.c b/security/dummy.c
index 649326b..6a0056b 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -977,6 +977,13 @@ static inline int dummy_key_permission(key_ref_t key_ref,
{
return 0;
}
+
+static int dummy_key_getsecurity(struct key *key, char **_buffer)
+{
+ *_buffer = NULL;
+ return 0;
+}
+
#endif /* CONFIG_KEYS */
struct security_operations dummy_security_ops;
@@ -1164,6 +1171,7 @@ void security_fixup_ops (struct security_operations *ops)
set_to_dummy_if_null(ops, key_alloc);
set_to_dummy_if_null(ops, key_free);
set_to_dummy_if_null(ops, key_permission);
+ set_to_dummy_if_null(ops, key_getsecurity);
#endif /* CONFIG_KEYS */
}
diff --git a/security/keys/compat.c b/security/keys/compat.c
index e10ec99..c766c68 100644
--- a/security/keys/compat.c
+++ b/security/keys/compat.c
@@ -79,6 +79,9 @@ asmlinkage long compat_sys_keyctl(u32 option,
case KEYCTL_ASSUME_AUTHORITY:
return keyctl_assume_authority(arg2);
+ case KEYCTL_GET_SECURITY:
+ return keyctl_get_security(arg2, compat_ptr(arg3), arg4);
+
default:
return -EOPNOTSUPP;
}
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index 1698bf9..56e963b 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -20,6 +20,7 @@
#include <linux/string.h>
#include <linux/err.h>
#include <linux/vmalloc.h>
+#include <linux/security.h>
#include <asm/uaccess.h>
#include "internal.h"
@@ -1080,6 +1081,66 @@ error:
} /* end keyctl_assume_authority() */
+/*
+ * get the security label of a key
+ * - the key must grant us view permission
+ * - if there's a buffer, we place up to buflen bytes of data into it
+ * - unless there's an error, we return the amount of information available,
+ * irrespective of how much we may have copied (including the terminal NUL)
+ * - implements keyctl(KEYCTL_GET_SECURITY)
+ */
+long keyctl_get_security(key_serial_t keyid,
+ char __user *buffer,
+ size_t buflen)
+{
+ struct key *key, *instkey;
+ key_ref_t key_ref;
+ char *context;
+ long ret;
+
+ key_ref = lookup_user_key(NULL, keyid, 0, 1, KEY_VIEW);
+ if (IS_ERR(key_ref)) {
+ if (PTR_ERR(key_ref) != -EACCES)
+ return PTR_ERR(key_ref);
+
+ /* viewing a key under construction is also permitted if we
+ * have the authorisation token handy */
+ instkey = key_get_instantiation_authkey(keyid);
+ if (IS_ERR(instkey))
+ return PTR_ERR(key_ref);
+ key_put(instkey);
+
+ key_ref = lookup_user_key(NULL, keyid, 0, 1, 0);
+ if (IS_ERR(key_ref))
+ return PTR_ERR(key_ref);
+ }
+
+ key = key_ref_to_ptr(key_ref);
+ ret = security_key_getsecurity(key, &context);
+ if (ret == 0) {
+ /* if no information was returned, give userspace an empty
+ * string */
+ ret = 1;
+ if (buffer && buflen > 0 &&
+ copy_to_user(buffer, "", 1) != 0)
+ ret = -EFAULT;
+ } else if (ret > 0) {
+ /* return as much data as there's room for */
+ if (buffer && buflen > 0) {
+ if (buflen > ret)
+ buflen = ret;
+
+ if (copy_to_user(buffer, context, buflen) != 0)
+ ret = -EFAULT;
+ }
+
+ kfree(context);
+ }
+
+ key_ref_put(key_ref);
+ return ret;
+}
+
/*****************************************************************************/
/*
* the key control system call
@@ -1160,6 +1221,11 @@ asmlinkage long sys_keyctl(int option, unsigned long arg2, unsigned long arg3,
case KEYCTL_ASSUME_AUTHORITY:
return keyctl_assume_authority((key_serial_t) arg2);
+ case KEYCTL_GET_SECURITY:
+ return keyctl_get_security((key_serial_t) arg2,
+ (char *) arg3,
+ (size_t) arg4);
+
default:
return -EOPNOTSUPP;
}
diff --git a/security/security.c b/security/security.c
index d15e56c..3e75b90 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1102,4 +1102,9 @@ int security_key_permission(key_ref_t key_ref,
return security_ops->key_permission(key_ref, context, perm);
}
+int security_key_getsecurity(struct key *key, char **_buffer)
+{
+ return security_ops->key_getsecurity(key, _buffer);
+}
+
#endif /* CONFIG_KEYS */
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index e5ed075..face4b4 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -5203,6 +5203,20 @@ static int selinux_key_permission(key_ref_t key_ref,
SECCLASS_KEY, perm, NULL);
}
+static int selinux_key_getsecurity(struct key *key, char **_buffer)
+{
+ struct key_security_struct *ksec = key->security;
+ char *context = NULL;
+ unsigned len;
+ int rc;
+
+ rc = security_sid_to_context(ksec->sid, &context, &len);
+ if (!rc)
+ rc = len;
+ *_buffer = context;
+ return rc;
+}
+
#endif
static struct security_operations selinux_ops = {
@@ -5382,9 +5396,10 @@ static struct security_operations selinux_ops = {
#endif
#ifdef CONFIG_KEYS
- .key_alloc = selinux_key_alloc,
- .key_free = selinux_key_free,
- .key_permission = selinux_key_permission,
+ .key_alloc = selinux_key_alloc,
+ .key_free = selinux_key_free,
+ .key_permission = selinux_key_permission,
+ .key_getsecurity = selinux_key_getsecurity,
#endif
};
^ permalink raw reply related [flat|nested] 8+ messages in thread