* Re: [PATCH v4 00/23] LSM: Module stacking for AppArmor
From: Kees Cook @ 2019-06-26 23:04 UTC (permalink / raw)
To: John Johansen
Cc: Casey Schaufler, casey.schaufler, jmorris, linux-security-module,
selinux, penguin-kernel, paul, sds
In-Reply-To: <47abf84c-208e-3a08-d50b-5d3f51aee271@canonical.com>
On Wed, Jun 26, 2019 at 02:11:23PM -0700, John Johansen wrote:
> On 6/26/19 2:04 PM, Kees Cook wrote:
> > On Wed, Jun 26, 2019 at 12:22:11PM -0700, Casey Schaufler wrote:
> >> This patchset provides the changes required for
> >> the AppArmor security module to stack safely with any other.
> >>
>
>
> here v
>
> >> Because of the changes to slot handling and the rework of
> >> "display" I have not included the Reviewed-by tags from the
> >> previous version.
>
>
> >>
> >> v4: Incorporate feedback from v3
> >> - Mark new lsm_<blob>_alloc functions static
> >> - Replace the lsm and slot fields of the security_hook_list
> >> with a pointer to a LSM allocated lsm_id structure. The
> >> LSM identifies if it needs a slot explicitly. Use the
> >> lsm_id rather than make security_add_hooks return the
> >> slot value.
> >> - Validate slot values used in security.c
> >> - Reworked the "display" process attribute handling so that
> >> it works right and doesn't use goofy list processing.
> >> - fix display value check in dentry_init_security
> >> - Replace audit_log of secids with '?' instead of deleting
> >> the audit log
> >
> > I think you missed adding my and John's Reviewed-bys from v3?
> >
> Casey stated why above
Oops! Thanks! I skimmed too fast and only read the "v4" log. :P
--
Kees Cook
^ permalink raw reply
* [GIT PULL] tpmdd updates for Linux v5.3
From: Jarkko Sakkinen @ 2019-06-26 22:50 UTC (permalink / raw)
To: torvalds
Cc: linux-kernel, linux-security-module, linux-integrity, jmorris,
mjg59
Hi,
My v5.3 PR contains two critical bug fixes and support for obtaining TPM
events triggered by ExitBootServices(). For the latter I have to give a
quite verbose explanation not least because I had to revisit all the
details myself to remember what was going on in Matthew's patches.
The preboot software stack maintains an event log that gets entries
every time something gets hashed to any of the PCR registers. What gets
hashed could be a component to be run or perhaps log of some actions
taken just to give couple of coarse examples. In general, anything
relevant for the boot process that the preboot software does gets hashed
and a log entry with a specific event type [1].
The main application for this is remote attestation and the reason why
it is useful is nicely put in the very first section of [1]:
"Attestation is used to provide information about the platform’s state
to a challenger. However, PCR contents are difficult to interpret;
therefore, attestation is typically more useful when the PCR contents
are accompanied by a measurement log. While not trusted on their own,
the measurement log contains a richer set of information than do the PCR
contents. The PCR contents are used to provide the validation of the
measurement log."
Because EFI_TCG2_PROTOCOL.GetEventLog() is not available after calling
ExitBootServices(), Linux EFI stub copies the event log to a custom
configuration table. Unfortunately, ExitBootServices() also generates
events and obviously these events do not get copied to that table.
Luckily firmware does this for us by providing a configuration table
identified by EFI_TCG2_FINAL_EVENTS_TABLE_GUID.
This PR essentially contains necessary changes to provide the full
event log for the use the user space that is concatenated from these
two partial event logs [2].
[1]
https://trustedcomputinggroup.org/resource/pc-client-specific-platform-firmware-profile-specification/
[2] The final concatenation is done in drivers/char/tpm/eventlog/efi.c
/Jarkko
The following changes since commit c88e40e07cd967dcdf37321a63ab6e8b0d881100:
Merge tag 'mfd-fixes-5.2-1' of
git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd (2019-06-25 03:41:03
+0800)
are available in the Git repository at:
git://git.infradead.org/users/jjs/linux-tpmdd.git tags/tpmdd-next-20190625
for you to fetch changes up to 166a2809d65b282272c474835ec22c882a39ca1b:
tpm: Don't duplicate events from the final event log in the TCG2 log (2019-06-
24 23:57:50 +0300)
----------------------------------------------------------------
tpmdd updates for Linux v5.3
----------------------------------------------------------------
Kees Cook (1):
tpm: Actually fail on TPM errors during "get random"
Matthew Garrett (6):
tpm: Abstract crypto agile event size calculations
tpm: Reserve the TPM final events table
tpm: Append the final event log to the TPM event log
efi: Attempt to get the TCG2 event log in the boot stub
Abstract out support for locating an EFI config table
tpm: Don't duplicate events from the final event log in the TCG2 log
Vadim Sukhomlinov (1):
tpm: Fix TPM 1.2 Shutdown sequence to prevent future TPM operations
drivers/char/tpm/eventlog/efi.c | 59 ++++++++--
drivers/char/tpm/eventlog/tpm2.c | 47 +-------
drivers/char/tpm/tpm-chip.c | 6 +-
drivers/char/tpm/tpm1-cmd.c | 7 +-
drivers/char/tpm/tpm2-cmd.c | 7 +-
drivers/firmware/efi/efi.c | 2 +
drivers/firmware/efi/libstub/efi-stub-helper.c | 15 +++
drivers/firmware/efi/libstub/efistub.h | 2 +
drivers/firmware/efi/libstub/fdt.c | 27 ++---
drivers/firmware/efi/libstub/tpm.c | 80 ++++++++++---
drivers/firmware/efi/tpm.c | 63 +++++++++-
include/linux/efi.h | 10 ++
include/linux/tpm_eventlog.h | 152 +++++++++++++++++++++++++
13 files changed, 378 insertions(+), 99 deletions(-)
^ permalink raw reply
* Re: [PATCH v4 00/23] LSM: Module stacking for AppArmor
From: Casey Schaufler @ 2019-06-26 21:25 UTC (permalink / raw)
To: Kees Cook
Cc: casey.schaufler, jmorris, linux-security-module, selinux,
john.johansen, penguin-kernel, paul, sds, casey
In-Reply-To: <201906261404.451588F@keescook>
On 6/26/2019 2:04 PM, Kees Cook wrote:
> On Wed, Jun 26, 2019 at 12:22:11PM -0700, Casey Schaufler wrote:
>> This patchset provides the changes required for
>> the AppArmor security module to stack safely with any other.
>>
>> Because of the changes to slot handling and the rework of
>> "display" I have not included the Reviewed-by tags from the
>> previous version.
>>
>> v4: Incorporate feedback from v3
>> - Mark new lsm_<blob>_alloc functions static
>> - Replace the lsm and slot fields of the security_hook_list
>> with a pointer to a LSM allocated lsm_id structure. The
>> LSM identifies if it needs a slot explicitly. Use the
>> lsm_id rather than make security_add_hooks return the
>> slot value.
>> - Validate slot values used in security.c
>> - Reworked the "display" process attribute handling so that
>> it works right and doesn't use goofy list processing.
>> - fix display value check in dentry_init_security
>> - Replace audit_log of secids with '?' instead of deleting
>> the audit log
> I think you missed adding my and John's Reviewed-bys from v3?
See the sentence just before "v4:". I thought that the changes
where sufficient to require re-review. If you don't think they
are, I will happily accept the Reviewed-bys.
^ permalink raw reply
* Re: [PATCH v4 00/23] LSM: Module stacking for AppArmor
From: John Johansen @ 2019-06-26 21:11 UTC (permalink / raw)
To: Kees Cook, Casey Schaufler
Cc: casey.schaufler, jmorris, linux-security-module, selinux,
penguin-kernel, paul, sds
In-Reply-To: <201906261404.451588F@keescook>
On 6/26/19 2:04 PM, Kees Cook wrote:
> On Wed, Jun 26, 2019 at 12:22:11PM -0700, Casey Schaufler wrote:
>> This patchset provides the changes required for
>> the AppArmor security module to stack safely with any other.
>>
here v
>> Because of the changes to slot handling and the rework of
>> "display" I have not included the Reviewed-by tags from the
>> previous version.
>>
>> v4: Incorporate feedback from v3
>> - Mark new lsm_<blob>_alloc functions static
>> - Replace the lsm and slot fields of the security_hook_list
>> with a pointer to a LSM allocated lsm_id structure. The
>> LSM identifies if it needs a slot explicitly. Use the
>> lsm_id rather than make security_add_hooks return the
>> slot value.
>> - Validate slot values used in security.c
>> - Reworked the "display" process attribute handling so that
>> it works right and doesn't use goofy list processing.
>> - fix display value check in dentry_init_security
>> - Replace audit_log of secids with '?' instead of deleting
>> the audit log
>
> I think you missed adding my and John's Reviewed-bys from v3?
>
Casey stated why above
^ permalink raw reply
* Re: [PATCH v4 00/23] LSM: Module stacking for AppArmor
From: Kees Cook @ 2019-06-26 21:04 UTC (permalink / raw)
To: Casey Schaufler
Cc: casey.schaufler, jmorris, linux-security-module, selinux,
john.johansen, penguin-kernel, paul, sds
In-Reply-To: <20190626192234.11725-1-casey@schaufler-ca.com>
On Wed, Jun 26, 2019 at 12:22:11PM -0700, Casey Schaufler wrote:
> This patchset provides the changes required for
> the AppArmor security module to stack safely with any other.
>
> Because of the changes to slot handling and the rework of
> "display" I have not included the Reviewed-by tags from the
> previous version.
>
> v4: Incorporate feedback from v3
> - Mark new lsm_<blob>_alloc functions static
> - Replace the lsm and slot fields of the security_hook_list
> with a pointer to a LSM allocated lsm_id structure. The
> LSM identifies if it needs a slot explicitly. Use the
> lsm_id rather than make security_add_hooks return the
> slot value.
> - Validate slot values used in security.c
> - Reworked the "display" process attribute handling so that
> it works right and doesn't use goofy list processing.
> - fix display value check in dentry_init_security
> - Replace audit_log of secids with '?' instead of deleting
> the audit log
I think you missed adding my and John's Reviewed-bys from v3?
--
Kees Cook
^ permalink raw reply
* Re: [RFC PATCH v3 09/12] LSM: x86/sgx: Introduce ->enclave_load() hook for Intel SGX
From: James Morris @ 2019-06-26 20:39 UTC (permalink / raw)
To: Dr. Greg
Cc: Jarkko Sakkinen, Sean Christopherson, linux-sgx, Dave Hansen,
Cedric Xing, Andy Lutomirski, Jethro Beekman, Stephen Smalley,
casey.schaufler, william.c.roberts, linux-security-module,
selinux
In-Reply-To: <20190623171626.GA25683@wind.enjellic.com>
On Sun, 23 Jun 2019, Dr. Greg wrote:
> The most relevant and important control with respect to whether or not
> an enclave should be allowed to execute is evaluation of the
> SIGSTRUCT. Given the trajectory that platform security is on, SGX is
> not going to be the last technology of its type nor the only
> technology that makes use of cryptographically based code provenance.
>
> As a result, if we are content with handing an opaque pointer of a
> descriptive struture to an LSM routine, a generic hook that is tasked
> with verifying code or execution environment provenance doesn't seem
> like it would need to be technology specific nor controversial.
>
> That leaves as the last thorny issue the question of dynamic
> allocation of memory for executable content. As we have stated
> before, and at the outset of this note, from a security perspective
> this is only, effectively, a binary question for the platform owner as
> to whether or not the concept should be allowed.
>
> A generic LSM hook, appropriately named, could execute that decision
> without being SGX specific. Arguably, the hook should be named to
> indicate that it is seeking approval for allocating memory to be used
> for anonymous executable content, since that is what it would be
> effectively requesting approval for, in the case of SGX.
>
> For completeness a third generic hook may be useful. The purpose of
> that hook would be to verify a block of memory as being
> measured or signed for consideration as executable content. Arguably
> that will have utility far beyond SGX.
>
> In the case of SGX it would address the issue as to whether or not a
> block of executable content in untrusted space is eligible for
> anonymous execution. That may be a useful security measure in order
> to provide some control over an enclave being used as a random
> execution oracle.
>
> It obviously has no security utility against the enclave author since,
> as we have noted before, it is possible for the enclave author to
> simply pull whatever code is desired over an encrypted network
> connection.
>
> > James Morris
>
> Hopefully these comments are a useful basis for further discussion.
Thanks, this is helpful.
--
James Morris
<jmorris@namei.org>
^ permalink raw reply
* Re: [PATCH v8 1/2] mm: security: introduce init_on_alloc=1 and init_on_free=1 boot options
From: Kees Cook @ 2019-06-26 20:23 UTC (permalink / raw)
To: Qian Cai
Cc: Catalin Marinas, Ard Biesheuvel, Alexander Potapenko,
Andrew Morton, Christoph Lameter, Masahiro Yamada, Michal Hocko,
James Morris, Serge E. Hallyn, Nick Desaulniers,
Kostya Serebryany, Dmitry Vyukov, Sandeep Patil, Laura Abbott,
Randy Dunlap, Jann Horn, Mark Rutland, Marco Elver, linux-mm,
linux-security-module, kernel-hardening, clang-built-linux
In-Reply-To: <1561572949.5154.81.camel@lca.pw>
On Wed, Jun 26, 2019 at 02:15:49PM -0400, Qian Cai wrote:
> On Wed, 2019-06-26 at 14:19 +0200, Alexander Potapenko wrote:
> > Both init_on_alloc and init_on_free default to zero, but those defaults
> > can be overridden with CONFIG_INIT_ON_ALLOC_DEFAULT_ON and
> > CONFIG_INIT_ON_FREE_DEFAULT_ON.
> > [...]
> > +static int __init early_init_on_alloc(char *buf)
> > +{
> > + int ret;
> > + bool bool_result;
> > +
> > + if (!buf)
> > + return -EINVAL;
> > + ret = kstrtobool(buf, &bool_result);
> > + if (bool_result)
> > + static_branch_enable(&init_on_alloc);
> > + else
> > + static_branch_disable(&init_on_alloc);
> > + return ret;
> > +}
> > +early_param("init_on_alloc", early_init_on_alloc);
>
> Do those really necessary need to be static keys?
>
> Adding either init_on_free=0 or init_on_alloc=0 to the kernel cmdline will
> generate a warning with kernels built with clang.
>
> [ 0.000000] static_key_disable(): static key 'init_on_free+0x0/0x4' used
> before call to jump_label_init()
> [ 0.000000] WARNING: CPU: 0 PID: 0 at ./include/linux/jump_label.h:317
> early_init_on_free+0x1c0/0x200
> [ 0.000000] Modules linked in:
> [ 0.000000] CPU: 0 PID: 0 Comm: swapper Not tainted 5.2.0-rc6-next-20190626+
> #9
> [ 0.000000] pstate: 60000089 (nZCv daIf -PAN -UAO)
I think the issue here is that arm64 doesn't initialize static keys
early enough.
init/main.c has the general case:
asmlinkage __visible void __init start_kernel(void)
{
...
setup_arch(&command_line);
...
smp_prepare_boot_cpu();
...
/* parameters may set static keys */
jump_label_init();
parse_early_param();
...
}
however, x86 does even earlier early params in setup_arch():
void __init setup_arch(char **cmdline_p)
{
...
jump_label_init();
...
parse_early_param();
...
}
arm64 does similar very early early params in setup_arch()[1] too,
but not jump_label_init() which is too late in smp_prepare_boot_cpu():
void __init setup_arch(char **cmdline_p)
{
...
parse_early_param();
...
}
void __init smp_prepare_boot_cpu(void)
{
...
jump_label_init();
...
}
I can send a patch to fix this...
-Kees
[1] since efd9e03facd07 ("arm64: Use static keys for CPU features")
> [ 0.000000] pc : early_init_on_free+0x1c0/0x200
> [ 0.000000] lr : early_init_on_free+0x1c0/0x200
> [ 0.000000] sp : ffff100012c07df0
> [ 0.000000] x29: ffff100012c07e20 x28: ffff1000110a01ec
> [ 0.000000] x27: 000000000000005f x26: ffff100011716cd0
> [ 0.000000] x25: ffff100010d36166 x24: ffff100010d3615d
> [ 0.000000] x23: ffff100010d364b5 x22: ffff1000117164a0
> [ 0.000000] x21: 0000000000000000 x20: 0000000000000000
> [ 0.000000] x19: 0000000000000000 x18: 000000000000002e
> [ 0.000000] x17: 000000000000000f x16: 0000000000000040
> [ 0.000000] x15: 0000000000000000 x14: 6c61632065726f66
> [ 0.000000] x13: 6562206465737520 x12: 273478302f307830
> [ 0.000000] x11: 0000000000000000 x10: 0000000000000000
> [ 0.000000] x9 : 0000000000000000 x8 : 0000000000000000
> [ 0.000000] x7 : 6d756a206f74206c x6 : ffff100014426625
> [ 0.000000] x5 : ffff100012c07b28 x4 : 0000000000000007
> [ 0.000000] x3 : ffff1000101aadf4 x2 : 0000000000000001
> [ 0.000000] x1 : 0000000000000001 x0 : 000000000000005d
> [ 0.000000] Call trace:
> [ 0.000000] early_init_on_free+0x1c0/0x200
> [ 0.000000] do_early_param+0xd0/0x104
> [ 0.000000] parse_args+0x1f0/0x524
> [ 0.000000] parse_early_param+0x70/0x8c
> [ 0.000000] setup_arch+0xa8/0x268
> [ 0.000000] start_kernel+0x80/0x560
>
--
Kees Cook
^ permalink raw reply
* Re: [PATCH V33 24/30] bpf: Restrict bpf when kernel lockdown is in confidentiality mode
From: James Morris @ 2019-06-26 20:22 UTC (permalink / raw)
To: Andy Lutomirski
Cc: Matthew Garrett, linux-security, LKML, Linux API, David Howells,
Alexei Starovoitov, Matthew Garrett, Network Development,
Chun-Yi Lee, Daniel Borkmann, linux-security-module
In-Reply-To: <CALCETrVUwQP7roLnW6kFG80Cc5U6X_T6AW+BTAftLccYGp8+Ow@mail.gmail.com>
[Adding the LSM mailing list: missed this patchset initially]
On Thu, 20 Jun 2019, Andy Lutomirski wrote:
> This patch exemplifies why I don't like this approach:
>
> > @@ -97,6 +97,7 @@ enum lockdown_reason {
> > LOCKDOWN_INTEGRITY_MAX,
> > LOCKDOWN_KCORE,
> > LOCKDOWN_KPROBES,
> > + LOCKDOWN_BPF,
> > LOCKDOWN_CONFIDENTIALITY_MAX,
>
> > --- a/security/lockdown/lockdown.c
> > +++ b/security/lockdown/lockdown.c
> > @@ -33,6 +33,7 @@ static char *lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX+1] = {
> > [LOCKDOWN_INTEGRITY_MAX] = "integrity",
> > [LOCKDOWN_KCORE] = "/proc/kcore access",
> > [LOCKDOWN_KPROBES] = "use of kprobes",
> > + [LOCKDOWN_BPF] = "use of bpf",
> > [LOCKDOWN_CONFIDENTIALITY_MAX] = "confidentiality",
>
> The text here says "use of bpf", but what this patch is *really* doing
> is locking down use of BPF to read kernel memory. If the details
> change, then every LSM needs to get updated, and we risk breaking user
> policies that are based on LSMs that offer excessively fine
> granularity.
Can you give an example of how the details might change?
> I'd be more comfortable if the LSM only got to see "confidentiality"
> or "integrity".
These are not sufficient for creating a useful policy for the SELinux
case.
--
James Morris
<jmorris@namei.org>
^ permalink raw reply
* [PATCH v4 02/23] LSM: Infrastructure management of the sock security
From: Casey Schaufler @ 2019-06-26 19:22 UTC (permalink / raw)
To: casey.schaufler, jmorris, linux-security-module, selinux
Cc: casey, keescook, john.johansen, penguin-kernel, paul, sds
In-Reply-To: <20190626192234.11725-1-casey@schaufler-ca.com>
Move management of the sock->sk_security blob out
of the individual security modules and into the security
infrastructure. Instead of allocating the blobs from within
the modules the modules tell the infrastructure how much
space is required, and the space is allocated there.
Reviewed-by: Kees Cook <keescook@chromium.org>
Reviewed-by: John Johansen <jojn.johansen@canonical.com>
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
include/linux/lsm_hooks.h | 1 +
security/apparmor/include/net.h | 6 ++-
security/apparmor/lsm.c | 38 ++++-----------
security/security.c | 36 +++++++++++++-
security/selinux/hooks.c | 78 +++++++++++++++----------------
security/selinux/include/objsec.h | 5 ++
security/selinux/netlabel.c | 23 ++++-----
security/smack/smack.h | 5 ++
security/smack/smack_lsm.c | 64 ++++++++++++-------------
security/smack/smack_netfilter.c | 8 ++--
10 files changed, 144 insertions(+), 120 deletions(-)
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index f9222a04968d..b353482ea348 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -2047,6 +2047,7 @@ struct lsm_blob_sizes {
int lbs_cred;
int lbs_file;
int lbs_inode;
+ int lbs_sock;
int lbs_superblock;
int lbs_ipc;
int lbs_msg_msg;
diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h
index 7334ac966d01..adac04e3b3cc 100644
--- a/security/apparmor/include/net.h
+++ b/security/apparmor/include/net.h
@@ -55,7 +55,11 @@ struct aa_sk_ctx {
struct aa_label *peer;
};
-#define SK_CTX(X) ((X)->sk_security)
+static inline struct aa_sk_ctx *aa_sock(const struct sock *sk)
+{
+ return sk->sk_security + apparmor_blob_sizes.lbs_sock;
+}
+
#define SOCK_ctx(X) SOCK_INODE(X)->i_security
#define DEFINE_AUDIT_NET(NAME, OP, SK, F, T, P) \
struct lsm_network_audit NAME ## _net = { .sk = (SK), \
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index 49d664ddff44..2716e7731279 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -757,33 +757,15 @@ static int apparmor_task_kill(struct task_struct *target, struct kernel_siginfo
return error;
}
-/**
- * apparmor_sk_alloc_security - allocate and attach the sk_security field
- */
-static int apparmor_sk_alloc_security(struct sock *sk, int family, gfp_t flags)
-{
- struct aa_sk_ctx *ctx;
-
- ctx = kzalloc(sizeof(*ctx), flags);
- if (!ctx)
- return -ENOMEM;
-
- SK_CTX(sk) = ctx;
-
- return 0;
-}
-
/**
* apparmor_sk_free_security - free the sk_security field
*/
static void apparmor_sk_free_security(struct sock *sk)
{
- struct aa_sk_ctx *ctx = SK_CTX(sk);
+ struct aa_sk_ctx *ctx = aa_sock(sk);
- SK_CTX(sk) = NULL;
aa_put_label(ctx->label);
aa_put_label(ctx->peer);
- kfree(ctx);
}
/**
@@ -792,8 +774,8 @@ static void apparmor_sk_free_security(struct sock *sk)
static void apparmor_sk_clone_security(const struct sock *sk,
struct sock *newsk)
{
- struct aa_sk_ctx *ctx = SK_CTX(sk);
- struct aa_sk_ctx *new = SK_CTX(newsk);
+ struct aa_sk_ctx *ctx = aa_sock(sk);
+ struct aa_sk_ctx *new = aa_sock(newsk);
new->label = aa_get_label(ctx->label);
new->peer = aa_get_label(ctx->peer);
@@ -844,7 +826,7 @@ static int apparmor_socket_post_create(struct socket *sock, int family,
label = aa_get_current_label();
if (sock->sk) {
- struct aa_sk_ctx *ctx = SK_CTX(sock->sk);
+ struct aa_sk_ctx *ctx = aa_sock(sock->sk);
aa_put_label(ctx->label);
ctx->label = aa_get_label(label);
@@ -1029,7 +1011,7 @@ static int apparmor_socket_shutdown(struct socket *sock, int how)
*/
static int apparmor_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
{
- struct aa_sk_ctx *ctx = SK_CTX(sk);
+ struct aa_sk_ctx *ctx = aa_sock(sk);
if (!skb->secmark)
return 0;
@@ -1042,7 +1024,7 @@ static int apparmor_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
static struct aa_label *sk_peer_label(struct sock *sk)
{
- struct aa_sk_ctx *ctx = SK_CTX(sk);
+ struct aa_sk_ctx *ctx = aa_sock(sk);
if (ctx->peer)
return ctx->peer;
@@ -1126,7 +1108,7 @@ static int apparmor_socket_getpeersec_dgram(struct socket *sock,
*/
static void apparmor_sock_graft(struct sock *sk, struct socket *parent)
{
- struct aa_sk_ctx *ctx = SK_CTX(sk);
+ struct aa_sk_ctx *ctx = aa_sock(sk);
if (!ctx->label)
ctx->label = aa_get_current_label();
@@ -1136,7 +1118,7 @@ static void apparmor_sock_graft(struct sock *sk, struct socket *parent)
static int apparmor_inet_conn_request(struct sock *sk, struct sk_buff *skb,
struct request_sock *req)
{
- struct aa_sk_ctx *ctx = SK_CTX(sk);
+ struct aa_sk_ctx *ctx = aa_sock(sk);
if (!skb->secmark)
return 0;
@@ -1153,6 +1135,7 @@ struct lsm_blob_sizes apparmor_blob_sizes __lsm_ro_after_init = {
.lbs_cred = sizeof(struct aa_task_ctx *),
.lbs_file = sizeof(struct aa_file_ctx),
.lbs_task = sizeof(struct aa_task_ctx),
+ .lbs_sock = sizeof(struct aa_sk_ctx),
};
static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = {
@@ -1189,7 +1172,6 @@ static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT(getprocattr, apparmor_getprocattr),
LSM_HOOK_INIT(setprocattr, apparmor_setprocattr),
- LSM_HOOK_INIT(sk_alloc_security, apparmor_sk_alloc_security),
LSM_HOOK_INIT(sk_free_security, apparmor_sk_free_security),
LSM_HOOK_INIT(sk_clone_security, apparmor_sk_clone_security),
@@ -1581,7 +1563,7 @@ static unsigned int apparmor_ip_postroute(void *priv,
if (sk == NULL)
return NF_ACCEPT;
- ctx = SK_CTX(sk);
+ ctx = aa_sock(sk);
if (!apparmor_secmark_check(ctx->label, OP_SENDMSG, AA_MAY_SEND,
skb->secmark, sk))
return NF_ACCEPT;
diff --git a/security/security.c b/security/security.c
index 86198e303203..2c0834db7976 100644
--- a/security/security.c
+++ b/security/security.c
@@ -32,6 +32,7 @@
#include <linux/string.h>
#include <linux/msg.h>
#include <net/flow.h>
+#include <net/sock.h>
#define MAX_LSM_EVM_XATTR 2
@@ -172,6 +173,7 @@ static void __init lsm_set_blob_sizes(struct lsm_blob_sizes *needed)
lsm_set_blob_size(&needed->lbs_inode, &blob_sizes.lbs_inode);
lsm_set_blob_size(&needed->lbs_ipc, &blob_sizes.lbs_ipc);
lsm_set_blob_size(&needed->lbs_msg_msg, &blob_sizes.lbs_msg_msg);
+ lsm_set_blob_size(&needed->lbs_sock, &blob_sizes.lbs_sock);
lsm_set_blob_size(&needed->lbs_superblock, &blob_sizes.lbs_superblock);
lsm_set_blob_size(&needed->lbs_task, &blob_sizes.lbs_task);
}
@@ -306,6 +308,7 @@ static void __init ordered_lsm_init(void)
init_debug("inode blob size = %d\n", blob_sizes.lbs_inode);
init_debug("ipc blob size = %d\n", blob_sizes.lbs_ipc);
init_debug("msg_msg blob size = %d\n", blob_sizes.lbs_msg_msg);
+ init_debug("sock blob size = %d\n", blob_sizes.lbs_sock);
init_debug("superblock blob size = %d\n", blob_sizes.lbs_superblock);
init_debug("task blob size = %d\n", blob_sizes.lbs_task);
@@ -605,6 +608,28 @@ static void __init lsm_early_task(struct task_struct *task)
panic("%s: Early task alloc failed.\n", __func__);
}
+/**
+ * lsm_sock_alloc - allocate a composite sock blob
+ * @sock: the sock that needs a blob
+ * @priority: allocation mode
+ *
+ * Allocate the sock blob for all the modules
+ *
+ * Returns 0, or -ENOMEM if memory can't be allocated.
+ */
+static int lsm_sock_alloc(struct sock *sock, gfp_t priority)
+{
+ if (blob_sizes.lbs_sock == 0) {
+ sock->sk_security = NULL;
+ return 0;
+ }
+
+ sock->sk_security = kzalloc(blob_sizes.lbs_sock, priority);
+ if (sock->sk_security == NULL)
+ return -ENOMEM;
+ return 0;
+}
+
/**
* lsm_superblock_alloc - allocate a composite superblock blob
* @sb: the superblock that needs a blob
@@ -2048,12 +2073,21 @@ EXPORT_SYMBOL(security_socket_getpeersec_dgram);
int security_sk_alloc(struct sock *sk, int family, gfp_t priority)
{
- return call_int_hook(sk_alloc_security, 0, sk, family, priority);
+ int rc = lsm_sock_alloc(sk, priority);
+
+ if (unlikely(rc))
+ return rc;
+ rc = call_int_hook(sk_alloc_security, 0, sk, family, priority);
+ if (unlikely(rc))
+ security_sk_free(sk);
+ return rc;
}
void security_sk_free(struct sock *sk)
{
call_void_hook(sk_free_security, sk);
+ kfree(sk->sk_security);
+ sk->sk_security = NULL;
}
void security_sk_clone(const struct sock *sk, struct sock *newsk)
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 7478d8eda00a..5d74ed35b728 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -4319,7 +4319,7 @@ static int socket_sockcreate_sid(const struct task_security_struct *tsec,
static int sock_has_perm(struct sock *sk, u32 perms)
{
- struct sk_security_struct *sksec = sk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(sk);
struct common_audit_data ad;
struct lsm_network_audit net = {0,};
@@ -4376,7 +4376,7 @@ static int selinux_socket_post_create(struct socket *sock, int family,
isec->initialized = LABEL_INITIALIZED;
if (sock->sk) {
- sksec = sock->sk->sk_security;
+ sksec = selinux_sock(sock->sk);
sksec->sclass = sclass;
sksec->sid = sid;
/* Allows detection of the first association on this socket */
@@ -4392,8 +4392,8 @@ static int selinux_socket_post_create(struct socket *sock, int family,
static int selinux_socket_socketpair(struct socket *socka,
struct socket *sockb)
{
- struct sk_security_struct *sksec_a = socka->sk->sk_security;
- struct sk_security_struct *sksec_b = sockb->sk->sk_security;
+ struct sk_security_struct *sksec_a = selinux_sock(socka->sk);
+ struct sk_security_struct *sksec_b = selinux_sock(sockb->sk);
sksec_a->peer_sid = sksec_b->sid;
sksec_b->peer_sid = sksec_a->sid;
@@ -4408,7 +4408,7 @@ static int selinux_socket_socketpair(struct socket *socka,
static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
{
struct sock *sk = sock->sk;
- struct sk_security_struct *sksec = sk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(sk);
u16 family;
int err;
@@ -4540,7 +4540,7 @@ static int selinux_socket_connect_helper(struct socket *sock,
struct sockaddr *address, int addrlen)
{
struct sock *sk = sock->sk;
- struct sk_security_struct *sksec = sk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(sk);
int err;
err = sock_has_perm(sk, SOCKET__CONNECT);
@@ -4711,9 +4711,9 @@ static int selinux_socket_unix_stream_connect(struct sock *sock,
struct sock *other,
struct sock *newsk)
{
- struct sk_security_struct *sksec_sock = sock->sk_security;
- struct sk_security_struct *sksec_other = other->sk_security;
- struct sk_security_struct *sksec_new = newsk->sk_security;
+ struct sk_security_struct *sksec_sock = selinux_sock(sock);
+ struct sk_security_struct *sksec_other = selinux_sock(other);
+ struct sk_security_struct *sksec_new = selinux_sock(newsk);
struct common_audit_data ad;
struct lsm_network_audit net = {0,};
int err;
@@ -4745,8 +4745,8 @@ static int selinux_socket_unix_stream_connect(struct sock *sock,
static int selinux_socket_unix_may_send(struct socket *sock,
struct socket *other)
{
- struct sk_security_struct *ssec = sock->sk->sk_security;
- struct sk_security_struct *osec = other->sk->sk_security;
+ struct sk_security_struct *ssec = selinux_sock(sock->sk);
+ struct sk_security_struct *osec = selinux_sock(other->sk);
struct common_audit_data ad;
struct lsm_network_audit net = {0,};
@@ -4788,7 +4788,7 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
u16 family)
{
int err = 0;
- struct sk_security_struct *sksec = sk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(sk);
u32 sk_sid = sksec->sid;
struct common_audit_data ad;
struct lsm_network_audit net = {0,};
@@ -4821,7 +4821,7 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
{
int err;
- struct sk_security_struct *sksec = sk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(sk);
u16 family = sk->sk_family;
u32 sk_sid = sksec->sid;
struct common_audit_data ad;
@@ -4889,13 +4889,15 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
return err;
}
-static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval,
- int __user *optlen, unsigned len)
+static int selinux_socket_getpeersec_stream(struct socket *sock,
+ char __user *optval,
+ int __user *optlen,
+ unsigned int len)
{
int err = 0;
char *scontext;
u32 scontext_len;
- struct sk_security_struct *sksec = sock->sk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(sock->sk);
u32 peer_sid = SECSID_NULL;
if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
@@ -4955,34 +4957,27 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *
static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
{
- struct sk_security_struct *sksec;
-
- sksec = kzalloc(sizeof(*sksec), priority);
- if (!sksec)
- return -ENOMEM;
+ struct sk_security_struct *sksec = selinux_sock(sk);
sksec->peer_sid = SECINITSID_UNLABELED;
sksec->sid = SECINITSID_UNLABELED;
sksec->sclass = SECCLASS_SOCKET;
selinux_netlbl_sk_security_reset(sksec);
- sk->sk_security = sksec;
return 0;
}
static void selinux_sk_free_security(struct sock *sk)
{
- struct sk_security_struct *sksec = sk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(sk);
- sk->sk_security = NULL;
selinux_netlbl_sk_security_free(sksec);
- kfree(sksec);
}
static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
{
- struct sk_security_struct *sksec = sk->sk_security;
- struct sk_security_struct *newsksec = newsk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(sk);
+ struct sk_security_struct *newsksec = selinux_sock(newsk);
newsksec->sid = sksec->sid;
newsksec->peer_sid = sksec->peer_sid;
@@ -4996,7 +4991,7 @@ static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
if (!sk)
*secid = SECINITSID_ANY_SOCKET;
else {
- struct sk_security_struct *sksec = sk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(sk);
*secid = sksec->sid;
}
@@ -5006,7 +5001,7 @@ static void selinux_sock_graft(struct sock *sk, struct socket *parent)
{
struct inode_security_struct *isec =
inode_security_novalidate(SOCK_INODE(parent));
- struct sk_security_struct *sksec = sk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(sk);
if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 ||
sk->sk_family == PF_UNIX)
@@ -5021,7 +5016,7 @@ static void selinux_sock_graft(struct sock *sk, struct socket *parent)
static int selinux_sctp_assoc_request(struct sctp_endpoint *ep,
struct sk_buff *skb)
{
- struct sk_security_struct *sksec = ep->base.sk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(ep->base.sk);
struct common_audit_data ad;
struct lsm_network_audit net = {0,};
u8 peerlbl_active;
@@ -5172,8 +5167,8 @@ static int selinux_sctp_bind_connect(struct sock *sk, int optname,
static void selinux_sctp_sk_clone(struct sctp_endpoint *ep, struct sock *sk,
struct sock *newsk)
{
- struct sk_security_struct *sksec = sk->sk_security;
- struct sk_security_struct *newsksec = newsk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(sk);
+ struct sk_security_struct *newsksec = selinux_sock(newsk);
/* If policy does not support SECCLASS_SCTP_SOCKET then call
* the non-sctp clone version.
@@ -5190,7 +5185,7 @@ static void selinux_sctp_sk_clone(struct sctp_endpoint *ep, struct sock *sk,
static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
struct request_sock *req)
{
- struct sk_security_struct *sksec = sk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(sk);
int err;
u16 family = req->rsk_ops->family;
u32 connsid;
@@ -5211,7 +5206,7 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
static void selinux_inet_csk_clone(struct sock *newsk,
const struct request_sock *req)
{
- struct sk_security_struct *newsksec = newsk->sk_security;
+ struct sk_security_struct *newsksec = selinux_sock(newsk);
newsksec->sid = req->secid;
newsksec->peer_sid = req->peer_secid;
@@ -5228,7 +5223,7 @@ static void selinux_inet_csk_clone(struct sock *newsk,
static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
{
u16 family = sk->sk_family;
- struct sk_security_struct *sksec = sk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(sk);
/* handle mapped IPv4 packets arriving via IPv6 sockets */
if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
@@ -5312,7 +5307,7 @@ static int selinux_tun_dev_attach_queue(void *security)
static int selinux_tun_dev_attach(struct sock *sk, void *security)
{
struct tun_security_struct *tunsec = security;
- struct sk_security_struct *sksec = sk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(sk);
/* we don't currently perform any NetLabel based labeling here and it
* isn't clear that we would want to do so anyway; while we could apply
@@ -5353,7 +5348,7 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
int err = 0;
u32 perm;
struct nlmsghdr *nlh;
- struct sk_security_struct *sksec = sk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(sk);
if (skb->len < NLMSG_HDRLEN) {
err = -EINVAL;
@@ -5494,7 +5489,7 @@ static unsigned int selinux_ip_output(struct sk_buff *skb,
return NF_ACCEPT;
/* standard practice, label using the parent socket */
- sksec = sk->sk_security;
+ sksec = selinux_sock(sk);
sid = sksec->sid;
} else
sid = SECINITSID_KERNEL;
@@ -5533,7 +5528,7 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
if (sk == NULL)
return NF_ACCEPT;
- sksec = sk->sk_security;
+ sksec = selinux_sock(sk);
ad.type = LSM_AUDIT_DATA_NET;
ad.u.net = &net;
@@ -5625,7 +5620,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb,
u32 skb_sid;
struct sk_security_struct *sksec;
- sksec = sk->sk_security;
+ sksec = selinux_sock(sk);
if (selinux_skb_peerlbl_sid(skb, family, &skb_sid))
return NF_DROP;
/* At this point, if the returned skb peerlbl is SECSID_NULL
@@ -5654,7 +5649,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb,
} else {
/* Locally generated packet, fetch the security label from the
* associated socket. */
- struct sk_security_struct *sksec = sk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(sk);
peer_sid = sksec->sid;
secmark_perm = PACKET__SEND;
}
@@ -6633,6 +6628,7 @@ struct lsm_blob_sizes selinux_blob_sizes __lsm_ro_after_init = {
.lbs_inode = sizeof(struct inode_security_struct),
.lbs_ipc = sizeof(struct ipc_security_struct),
.lbs_msg_msg = sizeof(struct msg_security_struct),
+ .lbs_sock = sizeof(struct sk_security_struct),
.lbs_superblock = sizeof(struct superblock_security_struct),
};
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
index d08d7e5d2f93..29f02b8f8f31 100644
--- a/security/selinux/include/objsec.h
+++ b/security/selinux/include/objsec.h
@@ -194,4 +194,9 @@ static inline struct superblock_security_struct *selinux_superblock(
return superblock->s_security + selinux_blob_sizes.lbs_superblock;
}
+static inline struct sk_security_struct *selinux_sock(const struct sock *sock)
+{
+ return sock->sk_security + selinux_blob_sizes.lbs_sock;
+}
+
#endif /* _SELINUX_OBJSEC_H_ */
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c
index 186e727b737b..c40914a157b7 100644
--- a/security/selinux/netlabel.c
+++ b/security/selinux/netlabel.c
@@ -31,6 +31,7 @@
#include <linux/gfp.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
+#include <linux/lsm_hooks.h>
#include <net/sock.h>
#include <net/netlabel.h>
#include <net/ip.h>
@@ -81,7 +82,7 @@ static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb,
static struct netlbl_lsm_secattr *selinux_netlbl_sock_genattr(struct sock *sk)
{
int rc;
- struct sk_security_struct *sksec = sk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(sk);
struct netlbl_lsm_secattr *secattr;
if (sksec->nlbl_secattr != NULL)
@@ -114,7 +115,7 @@ static struct netlbl_lsm_secattr *selinux_netlbl_sock_getattr(
const struct sock *sk,
u32 sid)
{
- struct sk_security_struct *sksec = sk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(sk);
struct netlbl_lsm_secattr *secattr = sksec->nlbl_secattr;
if (secattr == NULL)
@@ -249,7 +250,7 @@ int selinux_netlbl_skbuff_setsid(struct sk_buff *skb,
* being labeled by it's parent socket, if it is just exit */
sk = skb_to_full_sk(skb);
if (sk != NULL) {
- struct sk_security_struct *sksec = sk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(sk);
if (sksec->nlbl_state != NLBL_REQSKB)
return 0;
@@ -287,7 +288,7 @@ int selinux_netlbl_sctp_assoc_request(struct sctp_endpoint *ep,
{
int rc;
struct netlbl_lsm_secattr secattr;
- struct sk_security_struct *sksec = ep->base.sk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(ep->base.sk);
struct sockaddr *addr;
struct sockaddr_in addr4;
#if IS_ENABLED(CONFIG_IPV6)
@@ -370,7 +371,7 @@ int selinux_netlbl_inet_conn_request(struct request_sock *req, u16 family)
*/
void selinux_netlbl_inet_csk_clone(struct sock *sk, u16 family)
{
- struct sk_security_struct *sksec = sk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(sk);
if (family == PF_INET)
sksec->nlbl_state = NLBL_LABELED;
@@ -388,8 +389,8 @@ void selinux_netlbl_inet_csk_clone(struct sock *sk, u16 family)
*/
void selinux_netlbl_sctp_sk_clone(struct sock *sk, struct sock *newsk)
{
- struct sk_security_struct *sksec = sk->sk_security;
- struct sk_security_struct *newsksec = newsk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(sk);
+ struct sk_security_struct *newsksec = selinux_sock(newsk);
newsksec->nlbl_state = sksec->nlbl_state;
}
@@ -407,7 +408,7 @@ void selinux_netlbl_sctp_sk_clone(struct sock *sk, struct sock *newsk)
int selinux_netlbl_socket_post_create(struct sock *sk, u16 family)
{
int rc;
- struct sk_security_struct *sksec = sk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(sk);
struct netlbl_lsm_secattr *secattr;
if (family != PF_INET && family != PF_INET6)
@@ -522,7 +523,7 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock,
{
int rc = 0;
struct sock *sk = sock->sk;
- struct sk_security_struct *sksec = sk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(sk);
struct netlbl_lsm_secattr secattr;
if (selinux_netlbl_option(level, optname) &&
@@ -560,7 +561,7 @@ static int selinux_netlbl_socket_connect_helper(struct sock *sk,
struct sockaddr *addr)
{
int rc;
- struct sk_security_struct *sksec = sk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(sk);
struct netlbl_lsm_secattr *secattr;
/* connected sockets are allowed to disconnect when the address family
@@ -599,7 +600,7 @@ static int selinux_netlbl_socket_connect_helper(struct sock *sk,
int selinux_netlbl_socket_connect_locked(struct sock *sk,
struct sockaddr *addr)
{
- struct sk_security_struct *sksec = sk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(sk);
if (sksec->nlbl_state != NLBL_REQSKB &&
sksec->nlbl_state != NLBL_CONNLABELED)
diff --git a/security/smack/smack.h b/security/smack/smack.h
index caecbcba9942..4ac4bf3310d7 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -375,6 +375,11 @@ static inline struct smack_known **smack_ipc(const struct kern_ipc_perm *ipc)
return ipc->security + smack_blob_sizes.lbs_ipc;
}
+static inline struct socket_smack *smack_sock(const struct sock *sock)
+{
+ return sock->sk_security + smack_blob_sizes.lbs_sock;
+}
+
static inline struct superblock_smack *smack_superblock(
const struct super_block *superblock)
{
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 807eff2ccce9..fd69e1bd841b 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -1439,7 +1439,7 @@ static int smack_inode_getsecurity(struct inode *inode,
if (sock == NULL || sock->sk == NULL)
return -EOPNOTSUPP;
- ssp = sock->sk->sk_security;
+ ssp = smack_sock(sock->sk);
if (strcmp(name, XATTR_SMACK_IPIN) == 0)
isp = ssp->smk_in;
@@ -1821,7 +1821,7 @@ static int smack_file_receive(struct file *file)
if (inode->i_sb->s_magic == SOCKFS_MAGIC) {
sock = SOCKET_I(inode);
- ssp = sock->sk->sk_security;
+ ssp = smack_sock(sock->sk);
tsp = smack_cred(current_cred());
/*
* If the receiving process can't write to the
@@ -2231,11 +2231,7 @@ static void smack_task_to_inode(struct task_struct *p, struct inode *inode)
static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags)
{
struct smack_known *skp = smk_of_current();
- struct socket_smack *ssp;
-
- ssp = kzalloc(sizeof(struct socket_smack), gfp_flags);
- if (ssp == NULL)
- return -ENOMEM;
+ struct socket_smack *ssp = smack_sock(sk);
/*
* Sockets created by kernel threads receive web label.
@@ -2249,11 +2245,10 @@ static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags)
}
ssp->smk_packet = NULL;
- sk->sk_security = ssp;
-
return 0;
}
+#ifdef SMACK_IPV6_PORT_LABELING
/**
* smack_sk_free_security - Free a socket blob
* @sk: the socket
@@ -2262,7 +2257,6 @@ static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags)
*/
static void smack_sk_free_security(struct sock *sk)
{
-#ifdef SMACK_IPV6_PORT_LABELING
struct smk_port_label *spp;
if (sk->sk_family == PF_INET6) {
@@ -2275,9 +2269,8 @@ static void smack_sk_free_security(struct sock *sk)
}
rcu_read_unlock();
}
-#endif
- kfree(sk->sk_security);
}
+#endif
/**
* smack_ipv4host_label - check host based restrictions
@@ -2395,7 +2388,7 @@ static struct smack_known *smack_ipv6host_label(struct sockaddr_in6 *sip)
static int smack_netlabel(struct sock *sk, int labeled)
{
struct smack_known *skp;
- struct socket_smack *ssp = sk->sk_security;
+ struct socket_smack *ssp = smack_sock(sk);
int rc = 0;
/*
@@ -2440,7 +2433,7 @@ static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap)
int rc;
int sk_lbl;
struct smack_known *hkp;
- struct socket_smack *ssp = sk->sk_security;
+ struct socket_smack *ssp = smack_sock(sk);
struct smk_audit_info ad;
rcu_read_lock();
@@ -2516,7 +2509,7 @@ static void smk_ipv6_port_label(struct socket *sock, struct sockaddr *address)
{
struct sock *sk = sock->sk;
struct sockaddr_in6 *addr6;
- struct socket_smack *ssp = sock->sk->sk_security;
+ struct socket_smack *ssp = smack_sock(sock->sk);
struct smk_port_label *spp;
unsigned short port = 0;
@@ -2603,7 +2596,7 @@ static int smk_ipv6_port_check(struct sock *sk, struct sockaddr_in6 *address,
int act)
{
struct smk_port_label *spp;
- struct socket_smack *ssp = sk->sk_security;
+ struct socket_smack *ssp = smack_sock(sk);
struct smack_known *skp = NULL;
unsigned short port;
struct smack_known *object;
@@ -2697,7 +2690,7 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,
if (sock == NULL || sock->sk == NULL)
return -EOPNOTSUPP;
- ssp = sock->sk->sk_security;
+ ssp = smack_sock(sock->sk);
if (strcmp(name, XATTR_SMACK_IPIN) == 0)
ssp->smk_in = skp;
@@ -2745,7 +2738,7 @@ static int smack_socket_post_create(struct socket *sock, int family,
* Sockets created by kernel threads receive web label.
*/
if (unlikely(current->flags & PF_KTHREAD)) {
- ssp = sock->sk->sk_security;
+ ssp = smack_sock(sock->sk);
ssp->smk_in = &smack_known_web;
ssp->smk_out = &smack_known_web;
}
@@ -2770,8 +2763,8 @@ static int smack_socket_post_create(struct socket *sock, int family,
static int smack_socket_socketpair(struct socket *socka,
struct socket *sockb)
{
- struct socket_smack *asp = socka->sk->sk_security;
- struct socket_smack *bsp = sockb->sk->sk_security;
+ struct socket_smack *asp = smack_sock(socka->sk);
+ struct socket_smack *bsp = smack_sock(sockb->sk);
asp->smk_packet = bsp->smk_out;
bsp->smk_packet = asp->smk_out;
@@ -2825,7 +2818,7 @@ static int smack_socket_connect(struct socket *sock, struct sockaddr *sap,
return 0;
#ifdef SMACK_IPV6_SECMARK_LABELING
- ssp = sock->sk->sk_security;
+ ssp = smack_sock(sock->sk);
#endif
switch (sock->sk->sk_family) {
@@ -3566,9 +3559,9 @@ static int smack_unix_stream_connect(struct sock *sock,
{
struct smack_known *skp;
struct smack_known *okp;
- struct socket_smack *ssp = sock->sk_security;
- struct socket_smack *osp = other->sk_security;
- struct socket_smack *nsp = newsk->sk_security;
+ struct socket_smack *ssp = smack_sock(sock);
+ struct socket_smack *osp = smack_sock(other);
+ struct socket_smack *nsp = smack_sock(newsk);
struct smk_audit_info ad;
int rc = 0;
#ifdef CONFIG_AUDIT
@@ -3614,8 +3607,8 @@ static int smack_unix_stream_connect(struct sock *sock,
*/
static int smack_unix_may_send(struct socket *sock, struct socket *other)
{
- struct socket_smack *ssp = sock->sk->sk_security;
- struct socket_smack *osp = other->sk->sk_security;
+ struct socket_smack *ssp = smack_sock(sock->sk);
+ struct socket_smack *osp = smack_sock(other->sk);
struct smk_audit_info ad;
int rc;
@@ -3652,7 +3645,7 @@ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg,
struct sockaddr_in6 *sap = (struct sockaddr_in6 *) msg->msg_name;
#endif
#ifdef SMACK_IPV6_SECMARK_LABELING
- struct socket_smack *ssp = sock->sk->sk_security;
+ struct socket_smack *ssp = smack_sock(sock->sk);
struct smack_known *rsp;
#endif
int rc = 0;
@@ -3817,7 +3810,7 @@ static int smk_skb_to_addr_ipv6(struct sk_buff *skb, struct sockaddr_in6 *sip)
static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
{
struct netlbl_lsm_secattr secattr;
- struct socket_smack *ssp = sk->sk_security;
+ struct socket_smack *ssp = smack_sock(sk);
struct smack_known *skp = NULL;
int rc = 0;
struct smk_audit_info ad;
@@ -3934,7 +3927,7 @@ static int smack_socket_getpeersec_stream(struct socket *sock,
int slen = 1;
int rc = 0;
- ssp = sock->sk->sk_security;
+ ssp = smack_sock(sock->sk);
if (ssp->smk_packet != NULL) {
rcp = ssp->smk_packet->smk_known;
slen = strlen(rcp) + 1;
@@ -3984,7 +3977,7 @@ static int smack_socket_getpeersec_dgram(struct socket *sock,
switch (family) {
case PF_UNIX:
- ssp = sock->sk->sk_security;
+ ssp = smack_sock(sock->sk);
s = ssp->smk_out->smk_secid;
break;
case PF_INET:
@@ -3997,7 +3990,7 @@ static int smack_socket_getpeersec_dgram(struct socket *sock,
* Translate what netlabel gave us.
*/
if (sock != NULL && sock->sk != NULL)
- ssp = sock->sk->sk_security;
+ ssp = smack_sock(sock->sk);
netlbl_secattr_init(&secattr);
rc = netlbl_skbuff_getattr(skb, family, &secattr);
if (rc == 0) {
@@ -4035,7 +4028,7 @@ static void smack_sock_graft(struct sock *sk, struct socket *parent)
(sk->sk_family != PF_INET && sk->sk_family != PF_INET6))
return;
- ssp = sk->sk_security;
+ ssp = smack_sock(sk);
ssp->smk_in = skp;
ssp->smk_out = skp;
/* cssp->smk_packet is already set in smack_inet_csk_clone() */
@@ -4055,7 +4048,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
{
u16 family = sk->sk_family;
struct smack_known *skp;
- struct socket_smack *ssp = sk->sk_security;
+ struct socket_smack *ssp = smack_sock(sk);
struct netlbl_lsm_secattr secattr;
struct sockaddr_in addr;
struct iphdr *hdr;
@@ -4154,7 +4147,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
static void smack_inet_csk_clone(struct sock *sk,
const struct request_sock *req)
{
- struct socket_smack *ssp = sk->sk_security;
+ struct socket_smack *ssp = smack_sock(sk);
struct smack_known *skp;
if (req->peer_secid != 0) {
@@ -4558,6 +4551,7 @@ struct lsm_blob_sizes smack_blob_sizes __lsm_ro_after_init = {
.lbs_inode = sizeof(struct inode_smack),
.lbs_ipc = sizeof(struct smack_known *),
.lbs_msg_msg = sizeof(struct smack_known *),
+ .lbs_sock = sizeof(struct socket_smack),
.lbs_superblock = sizeof(struct superblock_smack),
};
@@ -4667,7 +4661,9 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT(socket_getpeersec_stream, smack_socket_getpeersec_stream),
LSM_HOOK_INIT(socket_getpeersec_dgram, smack_socket_getpeersec_dgram),
LSM_HOOK_INIT(sk_alloc_security, smack_sk_alloc_security),
+#ifdef SMACK_IPV6_PORT_LABELING
LSM_HOOK_INIT(sk_free_security, smack_sk_free_security),
+#endif
LSM_HOOK_INIT(sock_graft, smack_sock_graft),
LSM_HOOK_INIT(inet_conn_request, smack_inet_conn_request),
LSM_HOOK_INIT(inet_csk_clone, smack_inet_csk_clone),
diff --git a/security/smack/smack_netfilter.c b/security/smack/smack_netfilter.c
index e36d17835d4f..701a1cc1bdcc 100644
--- a/security/smack/smack_netfilter.c
+++ b/security/smack/smack_netfilter.c
@@ -31,8 +31,8 @@ static unsigned int smack_ipv6_output(void *priv,
struct socket_smack *ssp;
struct smack_known *skp;
- if (sk && sk->sk_security) {
- ssp = sk->sk_security;
+ if (sk && smack_sock(sk)) {
+ ssp = smack_sock(sk);
skp = ssp->smk_out;
skb->secmark = skp->smk_secid;
}
@@ -49,8 +49,8 @@ static unsigned int smack_ipv4_output(void *priv,
struct socket_smack *ssp;
struct smack_known *skp;
- if (sk && sk->sk_security) {
- ssp = sk->sk_security;
+ if (sk && smack_sock(sk)) {
+ ssp = smack_sock(sk);
skp = ssp->smk_out;
skb->secmark = skp->smk_secid;
}
--
2.20.1
^ permalink raw reply related
* [PATCH v4 23/23] AppArmor: Remove the exclusive flag
From: Casey Schaufler @ 2019-06-26 19:22 UTC (permalink / raw)
To: casey.schaufler, jmorris, linux-security-module, selinux
Cc: casey, keescook, john.johansen, penguin-kernel, paul, sds
In-Reply-To: <20190626192234.11725-1-casey@schaufler-ca.com>
With the inclusion of the "display" process attribute
mechanism AppArmor no longer needs to be treated as an
"exclusive" security module. Remove the flag that indicates
it is exclusive. Remove the stub getpeersec_dgram AppArmor
hook as it has no effect in the single LSM case and
interferes in the multiple LSM case.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
security/apparmor/lsm.c | 20 +-------------------
1 file changed, 1 insertion(+), 19 deletions(-)
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index 6d2eefc9b7c1..fb5798683ae1 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -1079,22 +1079,6 @@ static int apparmor_socket_getpeersec_stream(struct socket *sock,
return error;
}
-/**
- * apparmor_socket_getpeersec_dgram - get security label of packet
- * @sock: the peer socket
- * @skb: packet data
- * @secid: pointer to where to put the secid of the packet
- *
- * Sets the netlabel socket state on sk from parent
- */
-static int apparmor_socket_getpeersec_dgram(struct socket *sock,
- struct sk_buff *skb, u32 *secid)
-
-{
- /* TODO: requires secid support */
- return -ENOPROTOOPT;
-}
-
/**
* apparmor_sock_graft - Initialize newly created socket
* @sk: child sock
@@ -1195,8 +1179,6 @@ static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = {
#endif
LSM_HOOK_INIT(socket_getpeersec_stream,
apparmor_socket_getpeersec_stream),
- LSM_HOOK_INIT(socket_getpeersec_dgram,
- apparmor_socket_getpeersec_dgram),
LSM_HOOK_INIT(sock_graft, apparmor_sock_graft),
#ifdef CONFIG_NETWORK_SECMARK
LSM_HOOK_INIT(inet_conn_request, apparmor_inet_conn_request),
@@ -1707,7 +1689,7 @@ static int __init apparmor_init(void)
DEFINE_LSM(apparmor) = {
.name = "apparmor",
- .flags = LSM_FLAG_LEGACY_MAJOR | LSM_FLAG_EXCLUSIVE,
+ .flags = LSM_FLAG_LEGACY_MAJOR,
.enabled = &apparmor_enabled,
.blobs = &apparmor_blob_sizes,
.init = apparmor_init,
--
2.20.1
^ permalink raw reply related
* [PATCH v4 21/23] Audit: Store LSM audit information in an lsmblob
From: Casey Schaufler @ 2019-06-26 19:22 UTC (permalink / raw)
To: casey.schaufler, jmorris, linux-security-module, selinux
Cc: casey, keescook, john.johansen, penguin-kernel, paul, sds
In-Reply-To: <20190626192234.11725-1-casey@schaufler-ca.com>
Change the audit code to store full lsmblob data instead of
a single u32 secid. This allows for multiple security modules
to use the audit system at the same time. It also allows the
removal of scaffolding code that was included during the
revision of LSM interfaces.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
kernel/audit.h | 6 +++---
kernel/auditsc.c | 40 +++++++++++++---------------------------
2 files changed, 16 insertions(+), 30 deletions(-)
diff --git a/kernel/audit.h b/kernel/audit.h
index 29e29c6f4afb..a8dd479e9556 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -91,7 +91,7 @@ struct audit_names {
kuid_t uid;
kgid_t gid;
dev_t rdev;
- u32 osid;
+ struct lsmblob olsm;
struct audit_cap_data fcap;
unsigned int fcap_ver;
unsigned char type; /* record type */
@@ -148,7 +148,7 @@ struct audit_context {
kuid_t target_auid;
kuid_t target_uid;
unsigned int target_sessionid;
- struct lsmblob target_lsm;
+ struct lsmblob target_lsm;
char target_comm[TASK_COMM_LEN];
struct audit_tree_refs *trees, *first_trees;
@@ -165,7 +165,7 @@ struct audit_context {
kuid_t uid;
kgid_t gid;
umode_t mode;
- u32 osid;
+ struct lsmblob olsm;
int has_perm;
uid_t perm_uid;
gid_t perm_gid;
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 0478680cd0a8..ec8872430fb6 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -646,17 +646,15 @@ static int audit_filter_rules(struct task_struct *tsk,
if (f->lsm_rule) {
/* Find files that match */
if (name) {
- lsmblob_init(&blob, name->osid);
result = security_audit_rule_match(
- &blob,
+ &name->olsm,
f->type,
f->op,
f->lsm_rule);
} else if (ctx) {
list_for_each_entry(n, &ctx->names_list, list) {
- lsmblob_init(&blob, n->osid);
if (security_audit_rule_match(
- &blob,
+ &n->olsm,
f->type,
f->op,
f->lsm_rule)) {
@@ -668,8 +666,7 @@ static int audit_filter_rules(struct task_struct *tsk,
/* Find ipc objects that match */
if (!ctx || ctx->type != AUDIT_IPC)
break;
- lsmblob_init(&blob, ctx->ipc.osid);
- if (security_audit_rule_match(&blob,
+ if (security_audit_rule_match(&ctx->ipc.olsm,
f->type, f->op,
f->lsm_rule))
++result;
@@ -955,7 +952,7 @@ static int audit_log_pid_context(struct audit_context *context, pid_t pid,
from_kuid(&init_user_ns, uid), sessionid);
if (lsmblob_is_set(blob)) {
if (security_secid_to_secctx(blob, &lsmctx)) {
- audit_log_format(ab, " obj=(none)");
+ audit_log_format(ab, " obj=?");
rc = 1;
} else {
audit_log_format(ab, " obj=%s", lsmctx.context);
@@ -1187,19 +1184,17 @@ static void show_special(struct audit_context *context, int *call_panic)
context->socketcall.args[i]);
break; }
case AUDIT_IPC: {
- u32 osid = context->ipc.osid;
+ struct lsmblob *olsm = &context->ipc.olsm;
audit_log_format(ab, "ouid=%u ogid=%u mode=%#ho",
from_kuid(&init_user_ns, context->ipc.uid),
from_kgid(&init_user_ns, context->ipc.gid),
context->ipc.mode);
- if (osid) {
+ if (lsmblob_is_set(olsm)) {
struct lsmcontext lsmcxt;
- struct lsmblob blob;
- lsmblob_init(&blob, osid);
- if (security_secid_to_secctx(&blob, &lsmcxt)) {
- audit_log_format(ab, " osid=%u", osid);
+ if (security_secid_to_secctx(olsm, &lsmcxt)) {
+ audit_log_format(ab, " obj=?");
*call_panic = 1;
} else {
audit_log_format(ab, " obj=%s", lsmcxt.context);
@@ -1346,13 +1341,11 @@ static void audit_log_name(struct audit_context *context, struct audit_names *n,
from_kgid(&init_user_ns, n->gid),
MAJOR(n->rdev),
MINOR(n->rdev));
- if (n->osid != 0) {
- struct lsmblob blob;
+ if (lsmblob_is_set(&n->olsm)) {
struct lsmcontext lsmctx;
- lsmblob_init(&blob, n->osid);
- if (security_secid_to_secctx(&blob, &lsmctx)) {
- audit_log_format(ab, " osid=%u", n->osid);
+ if (security_secid_to_secctx(&n->olsm, &lsmctx)) {
+ audit_log_format(ab, " obj=?");
if (call_panic)
*call_panic = 2;
} else {
@@ -1906,17 +1899,13 @@ static inline int audit_copy_fcaps(struct audit_names *name,
void audit_copy_inode(struct audit_names *name, const struct dentry *dentry,
struct inode *inode, unsigned int flags)
{
- struct lsmblob blob;
-
name->ino = inode->i_ino;
name->dev = inode->i_sb->s_dev;
name->mode = inode->i_mode;
name->uid = inode->i_uid;
name->gid = inode->i_gid;
name->rdev = inode->i_rdev;
- security_inode_getsecid(inode, &blob);
- /* scaffolding until osid is updated */
- name->osid = blob.secid[0];
+ security_inode_getsecid(inode, &name->olsm);
if (flags & AUDIT_INODE_NOEVAL) {
name->fcap_ver = -1;
return;
@@ -2266,14 +2255,11 @@ void __audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat)
void __audit_ipc_obj(struct kern_ipc_perm *ipcp)
{
struct audit_context *context = audit_context();
- struct lsmblob blob;
context->ipc.uid = ipcp->uid;
context->ipc.gid = ipcp->gid;
context->ipc.mode = ipcp->mode;
context->ipc.has_perm = 0;
- security_ipc_getsecid(ipcp, &blob);
- /* scaffolding on the [0] - change "osid" to a lsmblob */
- context->ipc.osid = blob.secid[0];
+ security_ipc_getsecid(ipcp, &context->ipc.olsm);
context->type = AUDIT_IPC;
}
--
2.20.1
^ permalink raw reply related
* [PATCH v4 22/23] NET: Store LSM netlabel data in a lsmblob
From: Casey Schaufler @ 2019-06-26 19:22 UTC (permalink / raw)
To: casey.schaufler, jmorris, linux-security-module, selinux
Cc: casey, keescook, john.johansen, penguin-kernel, paul, sds
In-Reply-To: <20190626192234.11725-1-casey@schaufler-ca.com>
Netlabel uses LSM interfaces requiring an lsmblob and
the internal storage is used to pass information between
these interfaces, so change the internal data from a secid
to a lsmblob. Update the netlabel interfaces and their
callers to accomodate the change. This requires that the
modules using netlabel use the lsm_id.slot to access the
correct secid when using netlabel.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
include/net/netlabel.h | 8 ++--
net/ipv4/cipso_ipv4.c | 6 ++-
net/netlabel/netlabel_kapi.c | 6 +--
net/netlabel/netlabel_unlabeled.c | 57 +++++++++++------------------
net/netlabel/netlabel_unlabeled.h | 2 +-
security/selinux/hooks.c | 2 +-
security/selinux/include/security.h | 1 +
security/selinux/netlabel.c | 2 +-
security/selinux/ss/services.c | 4 +-
security/smack/smack.h | 1 +
security/smack/smack_lsm.c | 5 ++-
security/smack/smackfs.c | 10 +++--
12 files changed, 50 insertions(+), 54 deletions(-)
diff --git a/include/net/netlabel.h b/include/net/netlabel.h
index 72d6435fc16c..6c550455e69f 100644
--- a/include/net/netlabel.h
+++ b/include/net/netlabel.h
@@ -180,7 +180,7 @@ struct netlbl_lsm_catmap {
* @attr.mls: MLS sensitivity label
* @attr.mls.cat: MLS category bitmap
* @attr.mls.lvl: MLS sensitivity level
- * @attr.secid: LSM specific secid token
+ * @attr.lsmblob: LSM specific data
*
* Description:
* This structure is used to pass security attributes between NetLabel and the
@@ -215,7 +215,7 @@ struct netlbl_lsm_secattr {
struct netlbl_lsm_catmap *cat;
u32 lvl;
} mls;
- u32 secid;
+ struct lsmblob lsmblob;
} attr;
};
@@ -429,7 +429,7 @@ int netlbl_cfg_unlbl_static_add(struct net *net,
const void *addr,
const void *mask,
u16 family,
- u32 secid,
+ struct lsmblob *lsmblob,
struct netlbl_audit *audit_info);
int netlbl_cfg_unlbl_static_del(struct net *net,
const char *dev_name,
@@ -537,7 +537,7 @@ static inline int netlbl_cfg_unlbl_static_add(struct net *net,
const void *addr,
const void *mask,
u16 family,
- u32 secid,
+ struct lsmblob *lsmblob,
struct netlbl_audit *audit_info)
{
return -ENOSYS;
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
index f0165c5f376b..eb4939f38a14 100644
--- a/net/ipv4/cipso_ipv4.c
+++ b/net/ipv4/cipso_ipv4.c
@@ -1481,7 +1481,8 @@ static int cipso_v4_gentag_loc(const struct cipso_v4_doi *doi_def,
buffer[0] = CIPSO_V4_TAG_LOCAL;
buffer[1] = CIPSO_V4_TAG_LOC_BLEN;
- *(u32 *)&buffer[2] = secattr->attr.secid;
+ /* only one netlabel user - the first */
+ *(u32 *)&buffer[2] = secattr->attr.lsmblob.secid[0];
return CIPSO_V4_TAG_LOC_BLEN;
}
@@ -1501,7 +1502,8 @@ static int cipso_v4_parsetag_loc(const struct cipso_v4_doi *doi_def,
const unsigned char *tag,
struct netlbl_lsm_secattr *secattr)
{
- secattr->attr.secid = *(u32 *)&tag[2];
+ /* only one netlabel user - the first */
+ secattr->attr.lsmblob.secid[0] = *(u32 *)&tag[2];
secattr->flags |= NETLBL_SECATTR_SECID;
return 0;
diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c
index ee3e5b6471a6..724d44943543 100644
--- a/net/netlabel/netlabel_kapi.c
+++ b/net/netlabel/netlabel_kapi.c
@@ -210,7 +210,7 @@ int netlbl_cfg_unlbl_map_add(const char *domain,
* @addr: IP address in network byte order (struct in[6]_addr)
* @mask: address mask in network byte order (struct in[6]_addr)
* @family: address family
- * @secid: LSM secid value for the entry
+ * @lsmblob: LSM data value for the entry
* @audit_info: NetLabel audit information
*
* Description:
@@ -224,7 +224,7 @@ int netlbl_cfg_unlbl_static_add(struct net *net,
const void *addr,
const void *mask,
u16 family,
- u32 secid,
+ struct lsmblob *lsmblob,
struct netlbl_audit *audit_info)
{
u32 addr_len;
@@ -244,7 +244,7 @@ int netlbl_cfg_unlbl_static_add(struct net *net,
return netlbl_unlhsh_add(net,
dev_name, addr, mask, addr_len,
- secid, audit_info);
+ lsmblob, audit_info);
}
/**
diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c
index 4716e0011ba5..57ede7781c8f 100644
--- a/net/netlabel/netlabel_unlabeled.c
+++ b/net/netlabel/netlabel_unlabeled.c
@@ -80,7 +80,7 @@ struct netlbl_unlhsh_tbl {
#define netlbl_unlhsh_addr4_entry(iter) \
container_of(iter, struct netlbl_unlhsh_addr4, list)
struct netlbl_unlhsh_addr4 {
- u32 secid;
+ struct lsmblob lsmblob;
struct netlbl_af4list list;
struct rcu_head rcu;
@@ -88,7 +88,7 @@ struct netlbl_unlhsh_addr4 {
#define netlbl_unlhsh_addr6_entry(iter) \
container_of(iter, struct netlbl_unlhsh_addr6, list)
struct netlbl_unlhsh_addr6 {
- u32 secid;
+ struct lsmblob lsmblob;
struct netlbl_af6list list;
struct rcu_head rcu;
@@ -233,7 +233,7 @@ static struct netlbl_unlhsh_iface *netlbl_unlhsh_search_iface(int ifindex)
* @iface: the associated interface entry
* @addr: IPv4 address in network byte order
* @mask: IPv4 address mask in network byte order
- * @secid: LSM secid value for entry
+ * @lsmblob: LSM data value for entry
*
* Description:
* Add a new address entry into the unlabeled connection hash table using the
@@ -244,7 +244,7 @@ static struct netlbl_unlhsh_iface *netlbl_unlhsh_search_iface(int ifindex)
static int netlbl_unlhsh_add_addr4(struct netlbl_unlhsh_iface *iface,
const struct in_addr *addr,
const struct in_addr *mask,
- u32 secid)
+ struct lsmblob *lsmblob)
{
int ret_val;
struct netlbl_unlhsh_addr4 *entry;
@@ -256,7 +256,7 @@ static int netlbl_unlhsh_add_addr4(struct netlbl_unlhsh_iface *iface,
entry->list.addr = addr->s_addr & mask->s_addr;
entry->list.mask = mask->s_addr;
entry->list.valid = 1;
- entry->secid = secid;
+ entry->lsmblob = *lsmblob;
spin_lock(&netlbl_unlhsh_lock);
ret_val = netlbl_af4list_add(&entry->list, &iface->addr4_list);
@@ -273,7 +273,7 @@ static int netlbl_unlhsh_add_addr4(struct netlbl_unlhsh_iface *iface,
* @iface: the associated interface entry
* @addr: IPv6 address in network byte order
* @mask: IPv6 address mask in network byte order
- * @secid: LSM secid value for entry
+ * @lsmblob: LSM data value for entry
*
* Description:
* Add a new address entry into the unlabeled connection hash table using the
@@ -284,7 +284,7 @@ static int netlbl_unlhsh_add_addr4(struct netlbl_unlhsh_iface *iface,
static int netlbl_unlhsh_add_addr6(struct netlbl_unlhsh_iface *iface,
const struct in6_addr *addr,
const struct in6_addr *mask,
- u32 secid)
+ struct lsmblob *lsmblob)
{
int ret_val;
struct netlbl_unlhsh_addr6 *entry;
@@ -300,7 +300,7 @@ static int netlbl_unlhsh_add_addr6(struct netlbl_unlhsh_iface *iface,
entry->list.addr.s6_addr32[3] &= mask->s6_addr32[3];
entry->list.mask = *mask;
entry->list.valid = 1;
- entry->secid = secid;
+ entry->lsmblob = *lsmblob;
spin_lock(&netlbl_unlhsh_lock);
ret_val = netlbl_af6list_add(&entry->list, &iface->addr6_list);
@@ -379,7 +379,7 @@ int netlbl_unlhsh_add(struct net *net,
const void *addr,
const void *mask,
u32 addr_len,
- u32 secid,
+ struct lsmblob *lsmblob,
struct netlbl_audit *audit_info)
{
int ret_val;
@@ -388,7 +388,6 @@ int netlbl_unlhsh_add(struct net *net,
struct netlbl_unlhsh_iface *iface;
struct audit_buffer *audit_buf = NULL;
struct lsmcontext context;
- struct lsmblob blob;
if (addr_len != sizeof(struct in_addr) &&
addr_len != sizeof(struct in6_addr))
@@ -421,7 +420,7 @@ int netlbl_unlhsh_add(struct net *net,
const struct in_addr *addr4 = addr;
const struct in_addr *mask4 = mask;
- ret_val = netlbl_unlhsh_add_addr4(iface, addr4, mask4, secid);
+ ret_val = netlbl_unlhsh_add_addr4(iface, addr4, mask4, lsmblob);
if (audit_buf != NULL)
netlbl_af4list_audit_addr(audit_buf, 1,
dev_name,
@@ -434,7 +433,7 @@ int netlbl_unlhsh_add(struct net *net,
const struct in6_addr *addr6 = addr;
const struct in6_addr *mask6 = mask;
- ret_val = netlbl_unlhsh_add_addr6(iface, addr6, mask6, secid);
+ ret_val = netlbl_unlhsh_add_addr6(iface, addr6, mask6, lsmblob);
if (audit_buf != NULL)
netlbl_af6list_audit_addr(audit_buf, 1,
dev_name,
@@ -451,8 +450,7 @@ int netlbl_unlhsh_add(struct net *net,
unlhsh_add_return:
rcu_read_unlock();
if (audit_buf != NULL) {
- lsmblob_init(&blob, secid);
- if (security_secid_to_secctx(&blob, &context) == 0) {
+ if (security_secid_to_secctx(lsmblob, &context) == 0) {
audit_log_format(audit_buf, " sec_obj=%s",
context.context);
security_release_secctx(&context);
@@ -487,7 +485,6 @@ static int netlbl_unlhsh_remove_addr4(struct net *net,
struct audit_buffer *audit_buf;
struct net_device *dev;
struct lsmcontext context;
- struct lsmblob blob;
spin_lock(&netlbl_unlhsh_lock);
list_entry = netlbl_af4list_remove(addr->s_addr, mask->s_addr,
@@ -507,10 +504,8 @@ static int netlbl_unlhsh_remove_addr4(struct net *net,
addr->s_addr, mask->s_addr);
if (dev != NULL)
dev_put(dev);
- if (entry != NULL)
- lsmblob_init(&blob, entry->secid);
if (entry != NULL &&
- security_secid_to_secctx(&blob, &context) == 0) {
+ security_secid_to_secctx(&entry->lsmblob, &context) == 0) {
audit_log_format(audit_buf, " sec_obj=%s",
context.context);
security_release_secctx(&context);
@@ -551,7 +546,6 @@ static int netlbl_unlhsh_remove_addr6(struct net *net,
struct audit_buffer *audit_buf;
struct net_device *dev;
struct lsmcontext context;
- struct lsmblob blob;
spin_lock(&netlbl_unlhsh_lock);
list_entry = netlbl_af6list_remove(addr, mask, &iface->addr6_list);
@@ -570,10 +564,8 @@ static int netlbl_unlhsh_remove_addr6(struct net *net,
addr, mask);
if (dev != NULL)
dev_put(dev);
- if (entry != NULL)
- lsmblob_init(&blob, entry->secid);
if (entry != NULL &&
- security_secid_to_secctx(&blob, &context) == 0) {
+ security_secid_to_secctx(&entry->lsmblob, &context) == 0) {
audit_log_format(audit_buf, " sec_obj=%s",
context.context);
security_release_secctx(&context);
@@ -927,9 +919,8 @@ static int netlbl_unlabel_staticadd(struct sk_buff *skb,
if (ret_val != 0)
return ret_val;
- /* scaffolding with the [0] */
return netlbl_unlhsh_add(&init_net,
- dev_name, addr, mask, addr_len, blob.secid[0],
+ dev_name, addr, mask, addr_len, &blob,
&audit_info);
}
@@ -977,10 +968,8 @@ static int netlbl_unlabel_staticadddef(struct sk_buff *skb,
if (ret_val != 0)
return ret_val;
- /* scaffolding with the [0] */
return netlbl_unlhsh_add(&init_net,
- NULL, addr, mask, addr_len, blob.secid[0],
- &audit_info);
+ NULL, addr, mask, addr_len, &blob, &audit_info);
}
/**
@@ -1092,8 +1081,7 @@ static int netlbl_unlabel_staticlist_gen(u32 cmd,
struct net_device *dev;
struct lsmcontext context;
void *data;
- u32 secid;
- struct lsmblob blob;
+ struct lsmblob *lsmb;
data = genlmsg_put(cb_arg->skb, NETLINK_CB(cb_arg->nl_cb->skb).portid,
cb_arg->seq, &netlbl_unlabel_gnl_family,
@@ -1131,7 +1119,7 @@ static int netlbl_unlabel_staticlist_gen(u32 cmd,
if (ret_val != 0)
goto list_cb_failure;
- secid = addr4->secid;
+ lsmb = (struct lsmblob *)&addr4->lsmblob;
} else {
ret_val = nla_put_in6_addr(cb_arg->skb,
NLBL_UNLABEL_A_IPV6ADDR,
@@ -1145,11 +1133,10 @@ static int netlbl_unlabel_staticlist_gen(u32 cmd,
if (ret_val != 0)
goto list_cb_failure;
- secid = addr6->secid;
+ lsmb = (struct lsmblob *)&addr6->lsmblob;
}
- lsmblob_init(&blob, secid);
- ret_val = security_secid_to_secctx(&blob, &context);
+ ret_val = security_secid_to_secctx(lsmb, &context);
if (ret_val != 0)
goto list_cb_failure;
ret_val = nla_put(cb_arg->skb,
@@ -1500,7 +1487,7 @@ int netlbl_unlabel_getattr(const struct sk_buff *skb,
&iface->addr4_list);
if (addr4 == NULL)
goto unlabel_getattr_nolabel;
- secattr->attr.secid = netlbl_unlhsh_addr4_entry(addr4)->secid;
+ secattr->attr.lsmblob = netlbl_unlhsh_addr4_entry(addr4)->lsmblob;
break;
}
#if IS_ENABLED(CONFIG_IPV6)
@@ -1513,7 +1500,7 @@ int netlbl_unlabel_getattr(const struct sk_buff *skb,
&iface->addr6_list);
if (addr6 == NULL)
goto unlabel_getattr_nolabel;
- secattr->attr.secid = netlbl_unlhsh_addr6_entry(addr6)->secid;
+ secattr->attr.lsmblob = netlbl_unlhsh_addr6_entry(addr6)->lsmblob;
break;
}
#endif /* IPv6 */
diff --git a/net/netlabel/netlabel_unlabeled.h b/net/netlabel/netlabel_unlabeled.h
index 3a9e5dc9511b..dcff99695c97 100644
--- a/net/netlabel/netlabel_unlabeled.h
+++ b/net/netlabel/netlabel_unlabeled.h
@@ -225,7 +225,7 @@ int netlbl_unlhsh_add(struct net *net,
const void *addr,
const void *mask,
u32 addr_len,
- u32 secid,
+ struct lsmblob *lsmblob,
struct netlbl_audit *audit_info);
int netlbl_unlhsh_remove(struct net *net,
const char *dev_name,
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 8c93b07bb353..d90dfce15d44 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -6622,7 +6622,7 @@ struct lsm_blob_sizes selinux_blob_sizes __lsm_ro_after_init = {
.lbs_superblock = sizeof(struct superblock_security_struct),
};
-static struct lsm_id selinux_lsmid = { .lsm="selinux", .slot=LSMBLOB_NEEDED };
+struct lsm_id selinux_lsmid = { .lsm="selinux", .slot=LSMBLOB_NEEDED };
static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT(binder_set_context_mgr, selinux_binder_set_context_mgr),
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index b5b7c5aade8c..f0ca3879ba48 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -68,6 +68,7 @@
struct netlbl_lsm_secattr;
extern int selinux_enabled;
+extern struct lsm_id selinux_lsmid;
/* Policy capabilities */
enum {
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c
index c40914a157b7..120d50c1bcac 100644
--- a/security/selinux/netlabel.c
+++ b/security/selinux/netlabel.c
@@ -122,7 +122,7 @@ static struct netlbl_lsm_secattr *selinux_netlbl_sock_getattr(
return NULL;
if ((secattr->flags & NETLBL_SECATTR_SECID) &&
- (secattr->attr.secid == sid))
+ (secattr->attr.lsmblob.secid[selinux_lsmid.slot] == sid))
return secattr;
return NULL;
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index e3f5d6aece66..4ca0e006c3cc 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -3593,7 +3593,7 @@ int security_netlbl_secattr_to_sid(struct selinux_state *state,
if (secattr->flags & NETLBL_SECATTR_CACHE)
*sid = *(u32 *)secattr->cache->data;
else if (secattr->flags & NETLBL_SECATTR_SECID)
- *sid = secattr->attr.secid;
+ *sid = secattr->attr.lsmblob.secid[selinux_lsmid.slot];
else if (secattr->flags & NETLBL_SECATTR_MLS_LVL) {
rc = -EIDRM;
ctx = sidtab_search(sidtab, SECINITSID_NETMSG);
@@ -3666,7 +3666,7 @@ int security_netlbl_sid_to_secattr(struct selinux_state *state,
if (secattr->domain == NULL)
goto out;
- secattr->attr.secid = sid;
+ secattr->attr.lsmblob.secid[selinux_lsmid.slot] = sid;
secattr->flags |= NETLBL_SECATTR_DOMAIN_CPY | NETLBL_SECATTR_SECID;
mls_export_netlbl_lvl(policydb, ctx, secattr);
rc = mls_export_netlbl_cat(policydb, ctx, secattr);
diff --git a/security/smack/smack.h b/security/smack/smack.h
index 7cc3a3382fee..039bf5de56b4 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -320,6 +320,7 @@ void smk_destroy_label_list(struct list_head *list);
* Shared data.
*/
extern int smack_enabled;
+extern struct lsm_id smack_lsmid;
extern int smack_cipso_direct;
extern int smack_cipso_mapped;
extern struct smack_known *smack_net_ambient;
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 3d571c438dfa..a8d56ce00918 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -3741,7 +3741,8 @@ static struct smack_known *smack_from_secattr(struct netlbl_lsm_secattr *sap,
/*
* Looks like a fallback, which gives us a secid.
*/
- return smack_from_secid(sap->attr.secid);
+ return smack_from_secid(
+ sap->attr.lsmblob.secid[smack_lsmid.slot]);
/*
* Without guidance regarding the smack value
* for the packet fall back on the network
@@ -4558,7 +4559,7 @@ struct lsm_blob_sizes smack_blob_sizes __lsm_ro_after_init = {
.lbs_superblock = sizeof(struct superblock_smack),
};
-static struct lsm_id smack_lsmid = { .lsm="smack", .slot=LSMBLOB_NEEDED };
+struct lsm_id smack_lsmid = { .lsm="smack", .slot=LSMBLOB_NEEDED };
static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT(ptrace_access_check, smack_ptrace_access_check),
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
index faf2ea3968b3..6a4c468c200c 100644
--- a/security/smack/smackfs.c
+++ b/security/smack/smackfs.c
@@ -1150,6 +1150,7 @@ static void smk_net4addr_insert(struct smk_net4addr *new)
static ssize_t smk_write_net4addr(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
+ struct lsmblob lsmblob;
struct smk_net4addr *snp;
struct sockaddr_in newname;
char *smack;
@@ -1281,10 +1282,13 @@ static ssize_t smk_write_net4addr(struct file *file, const char __user *buf,
* this host so that incoming packets get labeled.
* but only if we didn't get the special CIPSO option
*/
- if (rc == 0 && skp != NULL)
+ if (rc == 0 && skp != NULL) {
+ lsmblob_init(&lsmblob, 0);
+ lsmblob.secid[smack_lsmid.slot] = snp->smk_label->smk_secid;
rc = netlbl_cfg_unlbl_static_add(&init_net, NULL,
- &snp->smk_host, &snp->smk_mask, PF_INET,
- snp->smk_label->smk_secid, &audit_info);
+ &snp->smk_host, &snp->smk_mask, PF_INET, &lsmblob,
+ &audit_info);
+ }
if (rc == 0)
rc = count;
--
2.20.1
^ permalink raw reply related
* [PATCH v4 20/23] LSM: security_secid_to_secctx in netlink netfilter
From: Casey Schaufler @ 2019-06-26 19:22 UTC (permalink / raw)
To: casey.schaufler, jmorris, linux-security-module, selinux
Cc: casey, keescook, john.johansen, penguin-kernel, paul, sds
In-Reply-To: <20190626192234.11725-1-casey@schaufler-ca.com>
Change netlink netfilter interfaces to use lsmcontext
pointers, and remove scaffolding.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
net/netfilter/nfnetlink_queue.c | 32 +++++++++++++-------------------
1 file changed, 13 insertions(+), 19 deletions(-)
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index 6da00c7add5b..69efb688383f 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -305,12 +305,10 @@ static int nfqnl_put_sk_uidgid(struct sk_buff *skb, struct sock *sk)
return -1;
}
-static u32 nfqnl_get_sk_secctx(struct sk_buff *skb, char **secdata)
+static u32 nfqnl_get_sk_secctx(struct sk_buff *skb, struct lsmcontext *context)
{
- u32 seclen = 0;
#if IS_ENABLED(CONFIG_NETWORK_SECMARK)
struct lsmblob blob;
- struct lsmcontext context;
if (!skb || !sk_fullsock(skb->sk))
return 0;
@@ -318,15 +316,16 @@ static u32 nfqnl_get_sk_secctx(struct sk_buff *skb, char **secdata)
read_lock_bh(&skb->sk->sk_callback_lock);
if (skb->secmark) {
+ /* Any LSM might be looking for the secmark */
lsmblob_init(&blob, skb->secmark);
- security_secid_to_secctx(&blob, &context);
- *secdata = context.context;
+ security_secid_to_secctx(&blob, context);
}
read_unlock_bh(&skb->sk->sk_callback_lock);
- seclen = context.len;
+ return context->len;
+#else
+ return 0;
#endif
- return seclen;
}
static u32 nfqnl_get_bridge_size(struct nf_queue_entry *entry)
@@ -402,8 +401,7 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
enum ip_conntrack_info uninitialized_var(ctinfo);
struct nfnl_ct_hook *nfnl_ct;
bool csum_verify;
- struct lsmcontext scaff; /* scaffolding */
- char *secdata = NULL;
+ struct lsmcontext context;
u32 seclen = 0;
size = nlmsg_total_size(sizeof(struct nfgenmsg))
@@ -470,7 +468,7 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
}
if ((queue->flags & NFQA_CFG_F_SECCTX) && entskb->sk) {
- seclen = nfqnl_get_sk_secctx(entskb, &secdata);
+ seclen = nfqnl_get_sk_secctx(entskb, &context);
if (seclen)
size += nla_total_size(seclen);
}
@@ -605,7 +603,7 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
nfqnl_put_sk_uidgid(skb, entskb->sk) < 0)
goto nla_put_failure;
- if (seclen && nla_put(skb, NFQA_SECCTX, seclen, secdata))
+ if (seclen && nla_put(skb, NFQA_SECCTX, context.len, context.context))
goto nla_put_failure;
if (ct && nfnl_ct->build(skb, ct, ctinfo, NFQA_CT, NFQA_CT_INFO) < 0)
@@ -633,10 +631,8 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
}
nlh->nlmsg_len = skb->len;
- if (seclen) {
- lsmcontext_init(&scaff, secdata, seclen, 0);
- security_release_secctx(&scaff);
- }
+ if (seclen)
+ security_release_secctx(&context);
return skb;
nla_put_failure:
@@ -644,10 +640,8 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
kfree_skb(skb);
net_err_ratelimited("nf_queue: error creating packet message\n");
nlmsg_failure:
- if (seclen) {
- lsmcontext_init(&scaff, secdata, seclen, 0);
- security_release_secctx(&scaff);
- }
+ if (seclen)
+ security_release_secctx(&context);
return NULL;
}
--
2.20.1
^ permalink raw reply related
* [PATCH v4 19/23] LSM: Use lsmcontext in security_inode_getsecctx
From: Casey Schaufler @ 2019-06-26 19:22 UTC (permalink / raw)
To: casey.schaufler, jmorris, linux-security-module, selinux
Cc: casey, keescook, john.johansen, penguin-kernel, paul, sds
In-Reply-To: <20190626192234.11725-1-casey@schaufler-ca.com>
Change the security_inode_getsecctx() interface to fill
a lsmcontext structure instead of data and length pointers.
This provides the information about which LSM created the
context so that security_release_secctx() can use the
correct hook. A lsmcontext is used within kernfs to store
the security information as well.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
fs/kernfs/dir.c | 8 ++------
fs/kernfs/inode.c | 34 ++++++++++++----------------------
fs/kernfs/kernfs-internal.h | 3 +--
fs/nfsd/nfs4xdr.c | 23 +++++++++--------------
include/linux/security.h | 5 +++--
security/security.c | 14 ++++++++++++--
6 files changed, 39 insertions(+), 48 deletions(-)
diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c
index 92afad387237..1d000289d8b7 100644
--- a/fs/kernfs/dir.c
+++ b/fs/kernfs/dir.c
@@ -532,12 +532,8 @@ void kernfs_put(struct kernfs_node *kn)
kfree_const(kn->name);
if (kn->iattr) {
- struct lsmcontext scaff; /* scaffolding */
- if (kn->iattr->ia_secdata) {
- lsmcontext_init(&scaff, kn->iattr->ia_secdata,
- kn->iattr->ia_secdata_len, 0);
- security_release_secctx(&scaff);
- }
+ if (kn->iattr->ia_context.context)
+ security_release_secctx(&kn->iattr->ia_context);
simple_xattrs_free(&kn->iattr->xattrs);
kmem_cache_free(kernfs_iattrs_cache, kn->iattr);
}
diff --git a/fs/kernfs/inode.c b/fs/kernfs/inode.c
index 02cde9dac5ee..ffbf7863306d 100644
--- a/fs/kernfs/inode.c
+++ b/fs/kernfs/inode.c
@@ -135,21 +135,14 @@ int kernfs_iop_setattr(struct dentry *dentry, struct iattr *iattr)
return error;
}
-static int kernfs_node_setsecdata(struct kernfs_iattrs *attrs, void **secdata,
- u32 *secdata_len)
+static void kernfs_node_setsecdata(struct kernfs_iattrs *attrs,
+ struct lsmcontext *cp)
{
- void *old_secdata;
- size_t old_secdata_len;
+ struct lsmcontext old_context;
- old_secdata = attrs->ia_secdata;
- old_secdata_len = attrs->ia_secdata_len;
-
- attrs->ia_secdata = *secdata;
- attrs->ia_secdata_len = *secdata_len;
-
- *secdata = old_secdata;
- *secdata_len = old_secdata_len;
- return 0;
+ old_context = attrs->ia_context;
+ attrs->ia_context = *cp;
+ *cp = old_context;
}
ssize_t kernfs_iop_listxattr(struct dentry *dentry, char *buf, size_t size)
@@ -192,8 +185,8 @@ static void kernfs_refresh_inode(struct kernfs_node *kn, struct inode *inode)
* persistent copy in kernfs_node.
*/
set_inode_attr(inode, &attrs->ia_iattr);
- security_inode_notifysecctx(inode, attrs->ia_secdata,
- attrs->ia_secdata_len);
+ security_inode_notifysecctx(inode, attrs->ia_context.context,
+ attrs->ia_context.len);
}
if (kernfs_type(kn) == KERNFS_DIR)
@@ -350,8 +343,6 @@ static int kernfs_security_xattr_set(const struct xattr_handler *handler,
struct kernfs_node *kn = inode->i_private;
struct kernfs_iattrs *attrs;
struct lsmcontext context;
- void *secdata;
- u32 secdata_len = 0;
int error;
attrs = kernfs_iattrs(kn);
@@ -361,18 +352,17 @@ static int kernfs_security_xattr_set(const struct xattr_handler *handler,
error = security_inode_setsecurity(inode, suffix, value, size, flags);
if (error)
return error;
- error = security_inode_getsecctx(inode, &secdata, &secdata_len);
+ error = security_inode_getsecctx(inode, &context);
if (error)
return error;
mutex_lock(&kernfs_mutex);
- error = kernfs_node_setsecdata(attrs, &secdata, &secdata_len);
+ kernfs_node_setsecdata(attrs, &context);
mutex_unlock(&kernfs_mutex);
- if (secdata) {
- lsmcontext_init(&context, secdata, secdata_len, 0);
+ if (context.context)
security_release_secctx(&context);
- }
+
return error;
}
diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h
index 0b7d197a904c..844a028d282f 100644
--- a/fs/kernfs/kernfs-internal.h
+++ b/fs/kernfs/kernfs-internal.h
@@ -21,8 +21,7 @@
struct kernfs_iattrs {
struct iattr ia_iattr;
- void *ia_secdata;
- u32 ia_secdata_len;
+ struct lsmcontext ia_context;
struct simple_xattrs xattrs;
};
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index bb3db033e144..1209083565dd 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -2304,11 +2304,11 @@ nfsd4_encode_layout_types(struct xdr_stream *xdr, u32 layout_types)
#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
static inline __be32
nfsd4_encode_security_label(struct xdr_stream *xdr, struct svc_rqst *rqstp,
- void *context, int len)
+ struct lsmcontext *context)
{
__be32 *p;
- p = xdr_reserve_space(xdr, len + 4 + 4 + 4);
+ p = xdr_reserve_space(xdr, context->len + 4 + 4 + 4);
if (!p)
return nfserr_resource;
@@ -2318,13 +2318,13 @@ nfsd4_encode_security_label(struct xdr_stream *xdr, struct svc_rqst *rqstp,
*/
*p++ = cpu_to_be32(0); /* lfs */
*p++ = cpu_to_be32(0); /* pi */
- p = xdr_encode_opaque(p, context, len);
+ p = xdr_encode_opaque(p, context->context, context->len);
return 0;
}
#else
static inline __be32
nfsd4_encode_security_label(struct xdr_stream *xdr, struct svc_rqst *rqstp,
- void *context, int len)
+ struct lsmcontext *context)
{ return 0; }
#endif
@@ -2420,9 +2420,7 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
__be32 status;
int err;
struct nfs4_acl *acl = NULL;
- struct lsmcontext scaff; /* scaffolding */
- void *context = NULL;
- int contextlen;
+ struct lsmcontext context;
bool contextsupport = false;
struct nfsd4_compoundres *resp = rqstp->rq_resp;
u32 minorversion = resp->cstate.minorversion;
@@ -2479,7 +2477,7 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
bmval0 & FATTR4_WORD0_SUPPORTED_ATTRS) {
if (exp->ex_flags & NFSEXP_SECURITY_LABEL)
err = security_inode_getsecctx(d_inode(dentry),
- &context, &contextlen);
+ &context);
else
err = -EOPNOTSUPP;
contextsupport = (err == 0);
@@ -2908,8 +2906,7 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
}
if (bmval2 & FATTR4_WORD2_SECURITY_LABEL) {
- status = nfsd4_encode_security_label(xdr, rqstp, context,
- contextlen);
+ status = nfsd4_encode_security_label(xdr, rqstp, &context);
if (status)
goto out;
}
@@ -2920,10 +2917,8 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
out:
#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
- if (context) {
- lsmcontext_init(&scaff, context, contextlen, 0); /*scaffolding*/
- security_release_secctx(&scaff);
- }
+ if (context.context)
+ security_release_secctx(&context);
#endif /* CONFIG_NFSD_V4_SECURITY_LABEL */
kfree(acl);
if (tempfh) {
diff --git a/include/linux/security.h b/include/linux/security.h
index 2674eb70c2d7..c16aea55be97 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -489,7 +489,7 @@ void security_release_secctx(struct lsmcontext *cp);
void security_inode_invalidate_secctx(struct inode *inode);
int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen);
int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen);
-int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen);
+int security_inode_getsecctx(struct inode *inode, struct lsmcontext *cp);
#else /* CONFIG_SECURITY */
static inline int call_lsm_notifier(enum lsm_event event, void *data)
@@ -1290,7 +1290,8 @@ static inline int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32
{
return -EOPNOTSUPP;
}
-static inline int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
+static inline int security_inode_getsecctx(struct inode *inode,
+ struct lsmcontext *cp)
{
return -EOPNOTSUPP;
}
diff --git a/security/security.c b/security/security.c
index 61cdc6bcd32e..45b9f905f5c0 100644
--- a/security/security.c
+++ b/security/security.c
@@ -2164,9 +2164,19 @@ int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
}
EXPORT_SYMBOL(security_inode_setsecctx);
-int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
+int security_inode_getsecctx(struct inode *inode, struct lsmcontext *cp)
{
- return call_int_hook(inode_getsecctx, -EOPNOTSUPP, inode, ctx, ctxlen);
+ int *display = current->security;
+ struct security_hook_list *hp;
+
+ hlist_for_each_entry(hp, &security_hook_heads.inode_getsecctx, list)
+ if (*display == LSMBLOB_INVALID ||
+ *display == hp->lsmid->slot) {
+ cp->slot = hp->lsmid->slot;
+ return hp->hook.inode_getsecctx(inode,
+ (void **)&cp->context, &cp->len);
+ }
+ return -EOPNOTSUPP;
}
EXPORT_SYMBOL(security_inode_getsecctx);
--
2.20.1
^ permalink raw reply related
* [PATCH v4 18/23] LSM: Use lsmcontext in security_dentry_init_security
From: Casey Schaufler @ 2019-06-26 19:22 UTC (permalink / raw)
To: casey.schaufler, jmorris, linux-security-module, selinux
Cc: casey, keescook, john.johansen, penguin-kernel, paul, sds
In-Reply-To: <20190626192234.11725-1-casey@schaufler-ca.com>
Change the security_dentry_init_security() interface to
fill an lsmcontext structure instead of a void * data area
and a length. The lone caller of this interface is NFS4,
which may make copies of the data using its own mechanisms.
A rework of the nfs4 code to use the lsmcontext properly
is a significant project, so the coward's way out is taken,
and the lsmcontext data from security_dentry_init_security()
is copied, then released directly.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
fs/nfs/nfs4proc.c | 26 ++++++++++++++++----------
include/linux/security.h | 7 +++----
security/security.c | 19 +++++++++++++++----
3 files changed, 34 insertions(+), 18 deletions(-)
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index af1c0db29c39..952f805965bb 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -113,6 +113,7 @@ static inline struct nfs4_label *
nfs4_label_init_security(struct inode *dir, struct dentry *dentry,
struct iattr *sattr, struct nfs4_label *label)
{
+ struct lsmcontext context;
int err;
if (label == NULL)
@@ -122,21 +123,26 @@ nfs4_label_init_security(struct inode *dir, struct dentry *dentry,
return NULL;
err = security_dentry_init_security(dentry, sattr->ia_mode,
- &dentry->d_name, (void **)&label->label, &label->len);
- if (err == 0)
- return label;
+ &dentry->d_name, &context);
+
+ if (err)
+ return NULL;
+
+ label->label = kmemdup(context.context, context.len, GFP_KERNEL);
+ if (label->label == NULL)
+ label = NULL;
+ else
+ label->len = context.len;
+
+ security_release_secctx(&context);
+
+ return label;
- return NULL;
}
static inline void
nfs4_label_release_security(struct nfs4_label *label)
{
- struct lsmcontext scaff; /* scaffolding */
-
- if (label) {
- lsmcontext_init(&scaff, label->label, label->len, 0);
- security_release_secctx(&scaff);
- }
+ kfree(label->label);
}
static inline u32 *nfs4_bitmask(struct nfs_server *server, struct nfs4_label *label)
{
diff --git a/include/linux/security.h b/include/linux/security.h
index 7255825aa697..2674eb70c2d7 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -352,8 +352,8 @@ int security_sb_clone_mnt_opts(const struct super_block *oldsb,
int security_add_mnt_opt(const char *option, const char *val,
int len, void **mnt_opts);
int security_dentry_init_security(struct dentry *dentry, int mode,
- const struct qstr *name, void **ctx,
- u32 *ctxlen);
+ const struct qstr *name,
+ struct lsmcontext *ctx);
int security_dentry_create_files_as(struct dentry *dentry, int mode,
struct qstr *name,
const struct cred *old,
@@ -724,8 +724,7 @@ static inline void security_inode_free(struct inode *inode)
static inline int security_dentry_init_security(struct dentry *dentry,
int mode,
const struct qstr *name,
- void **ctx,
- u32 *ctxlen)
+ struct lsmcontext *ctx)
{
return -EOPNOTSUPP;
}
diff --git a/security/security.c b/security/security.c
index 97b468f6e6a9..61cdc6bcd32e 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1024,11 +1024,22 @@ void security_inode_free(struct inode *inode)
}
int security_dentry_init_security(struct dentry *dentry, int mode,
- const struct qstr *name, void **ctx,
- u32 *ctxlen)
+ const struct qstr *name,
+ struct lsmcontext *cp)
{
- return call_int_hook(dentry_init_security, -EOPNOTSUPP, dentry, mode,
- name, ctx, ctxlen);
+ int *display = current->security;
+ struct security_hook_list *hp;
+
+ hlist_for_each_entry(hp, &security_hook_heads.dentry_init_security,
+ list)
+ if (*display == LSMBLOB_INVALID ||
+ *display == hp->lsmid->slot) {
+ cp->slot = hp->lsmid->slot;
+ return hp->hook.dentry_init_security(dentry, mode,
+ name, (void **)&cp->context, &cp->len);
+ }
+
+ return -EOPNOTSUPP;
}
EXPORT_SYMBOL(security_dentry_init_security);
--
2.20.1
^ permalink raw reply related
* [PATCH v4 17/23] LSM: Use lsmcontext in security_secid_to_secctx
From: Casey Schaufler @ 2019-06-26 19:22 UTC (permalink / raw)
To: casey.schaufler, jmorris, linux-security-module, selinux
Cc: casey, keescook, john.johansen, penguin-kernel, paul, sds
In-Reply-To: <20190626192234.11725-1-casey@schaufler-ca.com>
Replace the (secctx,seclen) pointer pair with a single
lsmcontext pointer to allow return of the LSM identifier
along with the context and context length. This allows
security_release_secctx() to know how to release the
context. Callers have been modified to use or save the
returned data from the new structure.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
drivers/android/binder.c | 24 ++++++---------
include/linux/security.h | 4 +--
include/net/scm.h | 9 ++----
kernel/audit.c | 29 +++++++-----------
kernel/auditsc.c | 31 +++++++------------
net/ipv4/ip_sockglue.c | 7 ++---
net/netfilter/nf_conntrack_netlink.c | 14 +++++----
net/netfilter/nf_conntrack_standalone.c | 7 ++---
net/netfilter/nfnetlink_queue.c | 5 +++-
net/netlabel/netlabel_unlabeled.c | 40 ++++++++-----------------
net/netlabel/netlabel_user.c | 7 ++---
security/security.c | 9 ++++--
12 files changed, 72 insertions(+), 114 deletions(-)
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 89e574be34cc..5d417a7b9bb3 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -2874,9 +2874,7 @@ static void binder_transaction(struct binder_proc *proc,
binder_size_t last_fixup_min_off = 0;
struct binder_context *context = proc->context;
int t_debug_id = atomic_inc_return(&binder_last_id);
- char *secctx = NULL;
- u32 secctx_sz = 0;
- struct lsmcontext scaff; /* scaffolding */
+ struct lsmcontext lsmctx;
e = binder_transaction_log_add(&binder_transaction_log);
e->debug_id = t_debug_id;
@@ -3123,14 +3121,14 @@ static void binder_transaction(struct binder_proc *proc,
struct lsmblob blob;
security_task_getsecid(proc->tsk, &blob);
- ret = security_secid_to_secctx(&blob, &secctx, &secctx_sz);
+ ret = security_secid_to_secctx(&blob, &lsmctx);
if (ret) {
return_error = BR_FAILED_REPLY;
return_error_param = ret;
return_error_line = __LINE__;
goto err_get_secctx_failed;
}
- extra_buffers_size += ALIGN(secctx_sz, sizeof(u64));
+ extra_buffers_size += ALIGN(lsmctx.len, sizeof(u64));
}
trace_binder_transaction(reply, t, target_node);
@@ -3149,19 +3147,17 @@ static void binder_transaction(struct binder_proc *proc,
t->buffer = NULL;
goto err_binder_alloc_buf_failed;
}
- if (secctx) {
+ if (lsmctx.context) {
size_t buf_offset = ALIGN(tr->data_size, sizeof(void *)) +
ALIGN(tr->offsets_size, sizeof(void *)) +
ALIGN(extra_buffers_size, sizeof(void *)) -
- ALIGN(secctx_sz, sizeof(u64));
+ ALIGN(lsmctx.len, sizeof(u64));
t->security_ctx = (uintptr_t)t->buffer->user_data + buf_offset;
binder_alloc_copy_to_buffer(&target_proc->alloc,
t->buffer, buf_offset,
- secctx, secctx_sz);
- lsmcontext_init(&scaff, secctx, secctx_sz, 0);
- security_release_secctx(&scaff);
- secctx = NULL;
+ lsmctx.context, lsmctx.len);
+ security_release_secctx(&lsmctx);
}
t->buffer->debug_id = t->debug_id;
t->buffer->transaction = t;
@@ -3481,10 +3477,8 @@ static void binder_transaction(struct binder_proc *proc,
t->buffer->transaction = NULL;
binder_alloc_free_buf(&target_proc->alloc, t->buffer);
err_binder_alloc_buf_failed:
- if (secctx) {
- lsmcontext_init(&scaff, secctx, secctx_sz, 0);
- security_release_secctx(&scaff);
- }
+ if (lsmctx.context)
+ security_release_secctx(&lsmctx);
err_get_secctx_failed:
kfree(tcomplete);
binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
diff --git a/include/linux/security.h b/include/linux/security.h
index 046012a7255f..7255825aa697 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -481,7 +481,7 @@ int security_setprocattr(const char *lsm, const char *name, void *value,
size_t size);
int security_netlink_send(struct sock *sk, struct sk_buff *skb);
int security_ismaclabel(const char *name);
-int security_secid_to_secctx(struct lsmblob *blob, char **secdata, u32 *seclen);
+int security_secid_to_secctx(struct lsmblob *blob, struct lsmcontext *cp);
int security_secctx_to_secid(const char *secdata, u32 seclen,
struct lsmblob *blob);
void security_release_secctx(struct lsmcontext *cp);
@@ -1263,7 +1263,7 @@ static inline int security_ismaclabel(const char *name)
}
static inline int security_secid_to_secctx(struct lsmblob *blob,
- char **secdata, u32 *seclen)
+ struct lsmcontext *cp)
{
return -EOPNOTSUPP;
}
diff --git a/include/net/scm.h b/include/net/scm.h
index 6c7c3c229e4a..4a6ad8caf423 100644
--- a/include/net/scm.h
+++ b/include/net/scm.h
@@ -93,17 +93,14 @@ static __inline__ int scm_send(struct socket *sock, struct msghdr *msg,
static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm)
{
struct lsmcontext context;
- char *secdata;
- u32 seclen;
int err;
if (test_bit(SOCK_PASSSEC, &sock->flags)) {
- err = security_secid_to_secctx(&scm->lsmblob, &secdata,
- &seclen);
+ err = security_secid_to_secctx(&scm->lsmblob, &context);
if (!err) {
- put_cmsg(msg, SOL_SOCKET, SCM_SECURITY, seclen, secdata);
- lsmcontext_init(&context, secdata, seclen, 0);/*scaffolding*/
+ put_cmsg(msg, SOL_SOCKET, SCM_SECURITY,
+ context.len, context.context);
security_release_secctx(&context);
}
}
diff --git a/kernel/audit.c b/kernel/audit.c
index f844a2a642e6..436c23429319 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -1191,9 +1191,8 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
struct audit_buffer *ab;
u16 msg_type = nlh->nlmsg_type;
struct audit_sig_info *sig_data;
- char *ctx = NULL;
u32 len;
- struct lsmcontext scaff; /* scaffolding */
+ struct lsmcontext context;
err = audit_netlink_ok(skb, msg_type);
if (err)
@@ -1431,25 +1430,22 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
case AUDIT_SIGNAL_INFO:
len = 0;
if (lsmblob_is_set(&audit_sig_lsm)) {
- err = security_secid_to_secctx(&audit_sig_lsm, &ctx,
- &len);
+ err = security_secid_to_secctx(&audit_sig_lsm,
+ &context);
if (err)
return err;
}
sig_data = kmalloc(sizeof(*sig_data) + len, GFP_KERNEL);
if (!sig_data) {
- if (lsmblob_is_set(&audit_sig_lsm)) {
- lsmcontext_init(&scaff, ctx, len, 0);
- security_release_secctx(&scaff);
- }
+ if (lsmblob_is_set(&audit_sig_lsm))
+ security_release_secctx(&context);
return -ENOMEM;
}
sig_data->uid = from_kuid(&init_user_ns, audit_sig_uid);
sig_data->pid = audit_sig_pid;
if (lsmblob_is_set(&audit_sig_lsm)) {
- memcpy(sig_data->ctx, ctx, len);
- lsmcontext_init(&scaff, ctx, len, 0);
- security_release_secctx(&scaff);
+ memcpy(sig_data->ctx, context.context, context.len);
+ security_release_secctx(&context);
}
audit_send_reply(skb, seq, AUDIT_SIGNAL_INFO, 0, 0,
sig_data, sizeof(*sig_data) + len);
@@ -2074,26 +2070,23 @@ void audit_log_key(struct audit_buffer *ab, char *key)
int audit_log_task_context(struct audit_buffer *ab)
{
- char *ctx = NULL;
- unsigned len;
int error;
struct lsmblob blob;
- struct lsmcontext scaff; /* scaffolding */
+ struct lsmcontext context;
security_task_getsecid(current, &blob);
if (!lsmblob_is_set(&blob))
return 0;
- error = security_secid_to_secctx(&blob, &ctx, &len);
+ error = security_secid_to_secctx(&blob, &context);
if (error) {
if (error != -EINVAL)
goto error_path;
return 0;
}
- audit_log_format(ab, " subj=%s", ctx);
- lsmcontext_init(&scaff, ctx, len, 0);
- security_release_secctx(&scaff);
+ audit_log_format(ab, " subj=%s", context.context);
+ security_release_secctx(&context);
return 0;
error_path:
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 9fab0e7d90c3..0478680cd0a8 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -943,9 +943,7 @@ static int audit_log_pid_context(struct audit_context *context, pid_t pid,
struct lsmblob *blob, char *comm)
{
struct audit_buffer *ab;
- struct lsmcontext lsmcxt;
- char *ctx = NULL;
- u32 len;
+ struct lsmcontext lsmctx;
int rc = 0;
ab = audit_log_start(context, GFP_KERNEL, AUDIT_OBJ_PID);
@@ -956,13 +954,12 @@ static int audit_log_pid_context(struct audit_context *context, pid_t pid,
from_kuid(&init_user_ns, auid),
from_kuid(&init_user_ns, uid), sessionid);
if (lsmblob_is_set(blob)) {
- if (security_secid_to_secctx(blob, &ctx, &len)) {
+ if (security_secid_to_secctx(blob, &lsmctx)) {
audit_log_format(ab, " obj=(none)");
rc = 1;
} else {
- audit_log_format(ab, " obj=%s", ctx);
- lsmcontext_init(&lsmcxt, ctx, len, 0); /*scaffolding*/
- security_release_secctx(&lsmcxt);
+ audit_log_format(ab, " obj=%s", lsmctx.context);
+ security_release_secctx(&lsmctx);
}
}
audit_log_format(ab, " ocomm=");
@@ -1174,7 +1171,6 @@ static void audit_log_fcaps(struct audit_buffer *ab, struct audit_names *name)
static void show_special(struct audit_context *context, int *call_panic)
{
- struct lsmcontext lsmcxt;
struct audit_buffer *ab;
int i;
@@ -1198,17 +1194,15 @@ static void show_special(struct audit_context *context, int *call_panic)
from_kgid(&init_user_ns, context->ipc.gid),
context->ipc.mode);
if (osid) {
- char *ctx = NULL;
- u32 len;
+ struct lsmcontext lsmcxt;
struct lsmblob blob;
lsmblob_init(&blob, osid);
- if (security_secid_to_secctx(&blob, &ctx, &len)) {
+ if (security_secid_to_secctx(&blob, &lsmcxt)) {
audit_log_format(ab, " osid=%u", osid);
*call_panic = 1;
} else {
- audit_log_format(ab, " obj=%s", ctx);
- lsmcontext_init(&lsmcxt, ctx, len, 0);
+ audit_log_format(ab, " obj=%s", lsmcxt.context);
security_release_secctx(&lsmcxt);
}
}
@@ -1353,20 +1347,17 @@ static void audit_log_name(struct audit_context *context, struct audit_names *n,
MAJOR(n->rdev),
MINOR(n->rdev));
if (n->osid != 0) {
- char *ctx = NULL;
- u32 len;
struct lsmblob blob;
- struct lsmcontext lsmcxt;
+ struct lsmcontext lsmctx;
lsmblob_init(&blob, n->osid);
- if (security_secid_to_secctx(&blob, &ctx, &len)) {
+ if (security_secid_to_secctx(&blob, &lsmctx)) {
audit_log_format(ab, " osid=%u", n->osid);
if (call_panic)
*call_panic = 2;
} else {
- audit_log_format(ab, " obj=%s", ctx);
- lsmcontext_init(&lsmcxt, ctx, len, 0); /* scaffolding */
- security_release_secctx(&lsmcxt);
+ audit_log_format(ab, " obj=%s", lsmctx.context);
+ security_release_secctx(&lsmctx);
}
}
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index 7834c357b60b..80ae0c5a1301 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -132,20 +132,17 @@ static void ip_cmsg_recv_security(struct msghdr *msg, struct sk_buff *skb)
{
struct lsmcontext context;
struct lsmblob lb;
- char *secdata;
- u32 seclen;
int err;
err = security_socket_getpeersec_dgram(NULL, skb, &lb);
if (err)
return;
- err = security_secid_to_secctx(&lb, &secdata, &seclen);
+ err = security_secid_to_secctx(&lb, &context);
if (err)
return;
- put_cmsg(msg, SOL_IP, SCM_SECURITY, seclen, secdata);
- lsmcontext_init(&context, secdata, seclen, 0); /* scaffolding */
+ put_cmsg(msg, SOL_IP, SCM_SECURITY, context.len, context.context);
security_release_secctx(&context);
}
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 6954e6600583..403307ff0fff 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -328,13 +328,12 @@ static int ctnetlink_dump_mark(struct sk_buff *skb, const struct nf_conn *ct)
static int ctnetlink_dump_secctx(struct sk_buff *skb, const struct nf_conn *ct)
{
struct nlattr *nest_secctx;
- int len, ret;
- char *secctx;
+ int ret;
struct lsmblob blob;
struct lsmcontext context;
lsmblob_init(&blob, ct->secmark);
- ret = security_secid_to_secctx(&blob, &secctx, &len);
+ ret = security_secid_to_secctx(&blob, &context);
if (ret)
return 0;
@@ -343,13 +342,12 @@ static int ctnetlink_dump_secctx(struct sk_buff *skb, const struct nf_conn *ct)
if (!nest_secctx)
goto nla_put_failure;
- if (nla_put_string(skb, CTA_SECCTX_NAME, secctx))
+ if (nla_put_string(skb, CTA_SECCTX_NAME, context.context))
goto nla_put_failure;
nla_nest_end(skb, nest_secctx);
ret = 0;
nla_put_failure:
- lsmcontext_init(&context, secctx, len, 0); /* scaffolding */
security_release_secctx(&context);
return ret;
}
@@ -620,12 +618,16 @@ static inline int ctnetlink_secctx_size(const struct nf_conn *ct)
#ifdef CONFIG_NF_CONNTRACK_SECMARK
int len, ret;
struct lsmblob blob;
+ struct lsmcontext context;
lsmblob_init(&blob, ct->secmark);
- ret = security_secid_to_secctx(&blob, NULL, &len);
+ ret = security_secid_to_secctx(&blob, &context);
if (ret)
return 0;
+ len = context.len;
+ security_release_secctx(&context);
+
return nla_total_size(0) /* CTA_SECCTX */
+ nla_total_size(sizeof(char) * len); /* CTA_SECCTX_NAME */
#else
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 79158ad0486e..fcb51ab2bb8b 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -173,19 +173,16 @@ static void ct_seq_stop(struct seq_file *s, void *v)
static void ct_show_secctx(struct seq_file *s, const struct nf_conn *ct)
{
int ret;
- u32 len;
- char *secctx;
struct lsmblob blob;
struct lsmcontext context;
lsmblob_init(&blob, ct->secmark);
- ret = security_secid_to_secctx(&blob, &secctx, &len);
+ ret = security_secid_to_secctx(&blob, &context);
if (ret)
return;
- seq_printf(s, "secctx=%s ", secctx);
+ seq_printf(s, "secctx=%s ", context.context);
- lsmcontext_init(&context, secctx, len, 0); /* scaffolding */
security_release_secctx(&context);
}
#else
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index fe8403ef4e89..6da00c7add5b 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -310,6 +310,7 @@ static u32 nfqnl_get_sk_secctx(struct sk_buff *skb, char **secdata)
u32 seclen = 0;
#if IS_ENABLED(CONFIG_NETWORK_SECMARK)
struct lsmblob blob;
+ struct lsmcontext context;
if (!skb || !sk_fullsock(skb->sk))
return 0;
@@ -318,10 +319,12 @@ static u32 nfqnl_get_sk_secctx(struct sk_buff *skb, char **secdata)
if (skb->secmark) {
lsmblob_init(&blob, skb->secmark);
- security_secid_to_secctx(&blob, secdata, &seclen);
+ security_secid_to_secctx(&blob, &context);
+ *secdata = context.context;
}
read_unlock_bh(&skb->sk->sk_callback_lock);
+ seclen = context.len;
#endif
return seclen;
}
diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c
index 15b1945853be..4716e0011ba5 100644
--- a/net/netlabel/netlabel_unlabeled.c
+++ b/net/netlabel/netlabel_unlabeled.c
@@ -388,8 +388,6 @@ int netlbl_unlhsh_add(struct net *net,
struct netlbl_unlhsh_iface *iface;
struct audit_buffer *audit_buf = NULL;
struct lsmcontext context;
- char *secctx = NULL;
- u32 secctx_len;
struct lsmblob blob;
if (addr_len != sizeof(struct in_addr) &&
@@ -454,12 +452,9 @@ int netlbl_unlhsh_add(struct net *net,
rcu_read_unlock();
if (audit_buf != NULL) {
lsmblob_init(&blob, secid);
- if (security_secid_to_secctx(&blob,
- &secctx,
- &secctx_len) == 0) {
- audit_log_format(audit_buf, " sec_obj=%s", secctx);
- /* scaffolding */
- lsmcontext_init(&context, secctx, secctx_len, 0);
+ if (security_secid_to_secctx(&blob, &context) == 0) {
+ audit_log_format(audit_buf, " sec_obj=%s",
+ context.context);
security_release_secctx(&context);
}
audit_log_format(audit_buf, " res=%u", ret_val == 0 ? 1 : 0);
@@ -492,8 +487,6 @@ static int netlbl_unlhsh_remove_addr4(struct net *net,
struct audit_buffer *audit_buf;
struct net_device *dev;
struct lsmcontext context;
- char *secctx;
- u32 secctx_len;
struct lsmblob blob;
spin_lock(&netlbl_unlhsh_lock);
@@ -517,11 +510,9 @@ static int netlbl_unlhsh_remove_addr4(struct net *net,
if (entry != NULL)
lsmblob_init(&blob, entry->secid);
if (entry != NULL &&
- security_secid_to_secctx(&blob,
- &secctx, &secctx_len) == 0) {
- audit_log_format(audit_buf, " sec_obj=%s", secctx);
- /* scaffolding */
- lsmcontext_init(&context, secctx, secctx_len, 0);
+ security_secid_to_secctx(&blob, &context) == 0) {
+ audit_log_format(audit_buf, " sec_obj=%s",
+ context.context);
security_release_secctx(&context);
}
audit_log_format(audit_buf, " res=%u", entry != NULL ? 1 : 0);
@@ -560,8 +551,6 @@ static int netlbl_unlhsh_remove_addr6(struct net *net,
struct audit_buffer *audit_buf;
struct net_device *dev;
struct lsmcontext context;
- char *secctx;
- u32 secctx_len;
struct lsmblob blob;
spin_lock(&netlbl_unlhsh_lock);
@@ -584,10 +573,9 @@ static int netlbl_unlhsh_remove_addr6(struct net *net,
if (entry != NULL)
lsmblob_init(&blob, entry->secid);
if (entry != NULL &&
- security_secid_to_secctx(&blob,
- &secctx, &secctx_len) == 0) {
- audit_log_format(audit_buf, " sec_obj=%s", secctx);
- lsmcontext_init(&context, secctx, secctx_len, 0);
+ security_secid_to_secctx(&blob, &context) == 0) {
+ audit_log_format(audit_buf, " sec_obj=%s",
+ context.context);
security_release_secctx(&context);
}
audit_log_format(audit_buf, " res=%u", entry != NULL ? 1 : 0);
@@ -1105,8 +1093,6 @@ static int netlbl_unlabel_staticlist_gen(u32 cmd,
struct lsmcontext context;
void *data;
u32 secid;
- char *secctx;
- u32 secctx_len;
struct lsmblob blob;
data = genlmsg_put(cb_arg->skb, NETLINK_CB(cb_arg->nl_cb->skb).portid,
@@ -1163,15 +1149,13 @@ static int netlbl_unlabel_staticlist_gen(u32 cmd,
}
lsmblob_init(&blob, secid);
- ret_val = security_secid_to_secctx(&blob, &secctx, &secctx_len);
+ ret_val = security_secid_to_secctx(&blob, &context);
if (ret_val != 0)
goto list_cb_failure;
ret_val = nla_put(cb_arg->skb,
NLBL_UNLABEL_A_SECCTX,
- secctx_len,
- secctx);
- /* scaffolding */
- lsmcontext_init(&context, secctx, secctx_len, 0);
+ context.len,
+ context.context);
security_release_secctx(&context);
if (ret_val != 0)
goto list_cb_failure;
diff --git a/net/netlabel/netlabel_user.c b/net/netlabel/netlabel_user.c
index 94aea4985b74..2d1307f65250 100644
--- a/net/netlabel/netlabel_user.c
+++ b/net/netlabel/netlabel_user.c
@@ -99,8 +99,6 @@ struct audit_buffer *netlbl_audit_start_common(int type,
{
struct audit_buffer *audit_buf;
struct lsmcontext context;
- char *secctx;
- u32 secctx_len;
struct lsmblob blob;
if (audit_enabled == AUDIT_OFF)
@@ -116,9 +114,8 @@ struct audit_buffer *netlbl_audit_start_common(int type,
lsmblob_init(&blob, audit_info->secid);
if (audit_info->secid != 0 &&
- security_secid_to_secctx(&blob, &secctx, &secctx_len) == 0) {
- audit_log_format(audit_buf, " subj=%s", secctx);
- lsmcontext_init(&context, secctx, secctx_len, 0);/*scaffolding*/
+ security_secid_to_secctx(&blob, &context) == 0) {
+ audit_log_format(audit_buf, " subj=%s", context.context);
security_release_secctx(&context);
}
diff --git a/security/security.c b/security/security.c
index 3563b1e2f8f9..97b468f6e6a9 100644
--- a/security/security.c
+++ b/security/security.c
@@ -2081,7 +2081,7 @@ int security_ismaclabel(const char *name)
}
EXPORT_SYMBOL(security_ismaclabel);
-int security_secid_to_secctx(struct lsmblob *blob, char **secdata, u32 *seclen)
+int security_secid_to_secctx(struct lsmblob *blob, struct lsmcontext *cp)
{
struct security_hook_list *hp;
int *display = current->security;
@@ -2089,10 +2089,13 @@ int security_secid_to_secctx(struct lsmblob *blob, char **secdata, u32 *seclen)
hlist_for_each_entry(hp, &security_hook_heads.secid_to_secctx, list) {
if (WARN_ON(hp->lsmid->slot < 0 || hp->lsmid->slot >= lsm_slot))
continue;
- if (*display == LSMBLOB_INVALID || *display == hp->lsmid->slot)
+ if (*display == LSMBLOB_INVALID ||
+ *display == hp->lsmid->slot) {
+ cp->slot = hp->lsmid->slot;
return hp->hook.secid_to_secctx(
blob->secid[hp->lsmid->slot],
- secdata, seclen);
+ &cp->context, &cp->len);
+ }
}
return 0;
}
--
2.20.1
^ permalink raw reply related
* [PATCH v4 16/23] LSM: Use lsmcontext in security_secid_to_secctx
From: Casey Schaufler @ 2019-06-26 19:22 UTC (permalink / raw)
To: casey.schaufler, jmorris, linux-security-module, selinux
Cc: casey, keescook, john.johansen, penguin-kernel, paul, sds
In-Reply-To: <20190626192234.11725-1-casey@schaufler-ca.com>
Replace the (secctx,seclen) pointer pair with a single
lsmcontext pointer to allow return of the LSM identifier
along with the context and context length. This allows
security_release_secctx() to know how to release the
context. Callers have been modified to use or save the
returned data from the new structure.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
drivers/android/binder.c | 10 +++++--
fs/kernfs/dir.c | 9 ++++--
fs/kernfs/inode.c | 7 +++--
fs/nfs/nfs4proc.c | 8 +++--
fs/nfsd/nfs4xdr.c | 7 +++--
include/linux/security.h | 39 +++++++++++++++++++++++--
include/net/scm.h | 4 ++-
kernel/audit.c | 14 ++++++---
kernel/auditsc.c | 12 ++++++--
net/ipv4/ip_sockglue.c | 4 ++-
net/netfilter/nf_conntrack_netlink.c | 4 ++-
net/netfilter/nf_conntrack_standalone.c | 4 ++-
net/netfilter/nfnetlink_queue.c | 13 ++++++---
net/netlabel/netlabel_unlabeled.c | 19 +++++++++---
net/netlabel/netlabel_user.c | 4 ++-
security/security.c | 12 ++++----
security/smack/smack_lsm.c | 14 ++++++---
17 files changed, 141 insertions(+), 43 deletions(-)
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 144ac4f1c24f..89e574be34cc 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -2876,6 +2876,7 @@ static void binder_transaction(struct binder_proc *proc,
int t_debug_id = atomic_inc_return(&binder_last_id);
char *secctx = NULL;
u32 secctx_sz = 0;
+ struct lsmcontext scaff; /* scaffolding */
e = binder_transaction_log_add(&binder_transaction_log);
e->debug_id = t_debug_id;
@@ -3158,7 +3159,8 @@ static void binder_transaction(struct binder_proc *proc,
binder_alloc_copy_to_buffer(&target_proc->alloc,
t->buffer, buf_offset,
secctx, secctx_sz);
- security_release_secctx(secctx, secctx_sz);
+ lsmcontext_init(&scaff, secctx, secctx_sz, 0);
+ security_release_secctx(&scaff);
secctx = NULL;
}
t->buffer->debug_id = t->debug_id;
@@ -3479,8 +3481,10 @@ static void binder_transaction(struct binder_proc *proc,
t->buffer->transaction = NULL;
binder_alloc_free_buf(&target_proc->alloc, t->buffer);
err_binder_alloc_buf_failed:
- if (secctx)
- security_release_secctx(secctx, secctx_sz);
+ if (secctx) {
+ lsmcontext_init(&scaff, secctx, secctx_sz, 0);
+ security_release_secctx(&scaff);
+ }
err_get_secctx_failed:
kfree(tcomplete);
binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c
index b84d635567d3..92afad387237 100644
--- a/fs/kernfs/dir.c
+++ b/fs/kernfs/dir.c
@@ -532,9 +532,12 @@ void kernfs_put(struct kernfs_node *kn)
kfree_const(kn->name);
if (kn->iattr) {
- if (kn->iattr->ia_secdata)
- security_release_secctx(kn->iattr->ia_secdata,
- kn->iattr->ia_secdata_len);
+ struct lsmcontext scaff; /* scaffolding */
+ if (kn->iattr->ia_secdata) {
+ lsmcontext_init(&scaff, kn->iattr->ia_secdata,
+ kn->iattr->ia_secdata_len, 0);
+ security_release_secctx(&scaff);
+ }
simple_xattrs_free(&kn->iattr->xattrs);
kmem_cache_free(kernfs_iattrs_cache, kn->iattr);
}
diff --git a/fs/kernfs/inode.c b/fs/kernfs/inode.c
index 0c1fd945ce42..02cde9dac5ee 100644
--- a/fs/kernfs/inode.c
+++ b/fs/kernfs/inode.c
@@ -349,6 +349,7 @@ static int kernfs_security_xattr_set(const struct xattr_handler *handler,
{
struct kernfs_node *kn = inode->i_private;
struct kernfs_iattrs *attrs;
+ struct lsmcontext context;
void *secdata;
u32 secdata_len = 0;
int error;
@@ -368,8 +369,10 @@ static int kernfs_security_xattr_set(const struct xattr_handler *handler,
error = kernfs_node_setsecdata(attrs, &secdata, &secdata_len);
mutex_unlock(&kernfs_mutex);
- if (secdata)
- security_release_secctx(secdata, secdata_len);
+ if (secdata) {
+ lsmcontext_init(&context, secdata, secdata_len, 0);
+ security_release_secctx(&context);
+ }
return error;
}
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 4dbb0ee23432..af1c0db29c39 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -131,8 +131,12 @@ nfs4_label_init_security(struct inode *dir, struct dentry *dentry,
static inline void
nfs4_label_release_security(struct nfs4_label *label)
{
- if (label)
- security_release_secctx(label->label, label->len);
+ struct lsmcontext scaff; /* scaffolding */
+
+ if (label) {
+ lsmcontext_init(&scaff, label->label, label->len, 0);
+ security_release_secctx(&scaff);
+ }
}
static inline u32 *nfs4_bitmask(struct nfs_server *server, struct nfs4_label *label)
{
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 3de42a729093..bb3db033e144 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -2420,6 +2420,7 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
__be32 status;
int err;
struct nfs4_acl *acl = NULL;
+ struct lsmcontext scaff; /* scaffolding */
void *context = NULL;
int contextlen;
bool contextsupport = false;
@@ -2919,8 +2920,10 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
out:
#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
- if (context)
- security_release_secctx(context, contextlen);
+ if (context) {
+ lsmcontext_init(&scaff, context, contextlen, 0); /*scaffolding*/
+ security_release_secctx(&scaff);
+ }
#endif /* CONFIG_NFSD_V4_SECURITY_LABEL */
kfree(acl);
if (tempfh) {
diff --git a/include/linux/security.h b/include/linux/security.h
index d310fa3942ce..046012a7255f 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -76,6 +76,41 @@ enum lsm_event {
LSM_POLICY_CHANGE,
};
+/*
+ * A "security context" is the text representation of
+ * the information used by LSMs.
+ * This structure contains the string, its length, and which LSM
+ * it is useful for.
+ */
+struct lsmcontext {
+ char *context; /* Provided by the module */
+ u32 len;
+ int slot; /* Identifies the module */
+};
+
+/**
+ * lsmcontext_init - initialize an lsmcontext structure.
+ * @cp: Pointer to the context to initialize
+ * @context: Initial context, or NULL
+ * @size: Size of context, or 0
+ * @slot: Which LSM provided the context
+ *
+ * Fill in the lsmcontext from the provided information.
+ * This is a scaffolding function that will be removed when
+ * lsmcontext integration is complete.
+ */
+static inline void lsmcontext_init(struct lsmcontext *cp, char *context,
+ u32 size, int slot)
+{
+ cp->slot = slot;
+ cp->context = context;
+
+ if (context == NULL || size == 0)
+ cp->len = 0;
+ else
+ cp->len = strlen(context);
+}
+
/*
* Data exported by the security modules
*
@@ -449,7 +484,7 @@ int security_ismaclabel(const char *name);
int security_secid_to_secctx(struct lsmblob *blob, char **secdata, u32 *seclen);
int security_secctx_to_secid(const char *secdata, u32 seclen,
struct lsmblob *blob);
-void security_release_secctx(char *secdata, u32 seclen);
+void security_release_secctx(struct lsmcontext *cp);
void security_inode_invalidate_secctx(struct inode *inode);
int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen);
@@ -1240,7 +1275,7 @@ static inline int security_secctx_to_secid(const char *secdata,
return -EOPNOTSUPP;
}
-static inline void security_release_secctx(char *secdata, u32 seclen)
+static inline void security_release_secctx(struct lsmcontext *cp)
{
}
diff --git a/include/net/scm.h b/include/net/scm.h
index 31ae605fcc0a..6c7c3c229e4a 100644
--- a/include/net/scm.h
+++ b/include/net/scm.h
@@ -92,6 +92,7 @@ static __inline__ int scm_send(struct socket *sock, struct msghdr *msg,
#ifdef CONFIG_SECURITY_NETWORK
static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm)
{
+ struct lsmcontext context;
char *secdata;
u32 seclen;
int err;
@@ -102,7 +103,8 @@ static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct sc
if (!err) {
put_cmsg(msg, SOL_SOCKET, SCM_SECURITY, seclen, secdata);
- security_release_secctx(secdata, seclen);
+ lsmcontext_init(&context, secdata, seclen, 0);/*scaffolding*/
+ security_release_secctx(&context);
}
}
}
diff --git a/kernel/audit.c b/kernel/audit.c
index 1b51e907f131..f844a2a642e6 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -1193,6 +1193,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
struct audit_sig_info *sig_data;
char *ctx = NULL;
u32 len;
+ struct lsmcontext scaff; /* scaffolding */
err = audit_netlink_ok(skb, msg_type);
if (err)
@@ -1437,15 +1438,18 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
}
sig_data = kmalloc(sizeof(*sig_data) + len, GFP_KERNEL);
if (!sig_data) {
- if (lsmblob_is_set(&audit_sig_lsm))
- security_release_secctx(ctx, len);
+ if (lsmblob_is_set(&audit_sig_lsm)) {
+ lsmcontext_init(&scaff, ctx, len, 0);
+ security_release_secctx(&scaff);
+ }
return -ENOMEM;
}
sig_data->uid = from_kuid(&init_user_ns, audit_sig_uid);
sig_data->pid = audit_sig_pid;
if (lsmblob_is_set(&audit_sig_lsm)) {
memcpy(sig_data->ctx, ctx, len);
- security_release_secctx(ctx, len);
+ lsmcontext_init(&scaff, ctx, len, 0);
+ security_release_secctx(&scaff);
}
audit_send_reply(skb, seq, AUDIT_SIGNAL_INFO, 0, 0,
sig_data, sizeof(*sig_data) + len);
@@ -2074,6 +2078,7 @@ int audit_log_task_context(struct audit_buffer *ab)
unsigned len;
int error;
struct lsmblob blob;
+ struct lsmcontext scaff; /* scaffolding */
security_task_getsecid(current, &blob);
if (!lsmblob_is_set(&blob))
@@ -2087,7 +2092,8 @@ int audit_log_task_context(struct audit_buffer *ab)
}
audit_log_format(ab, " subj=%s", ctx);
- security_release_secctx(ctx, len);
+ lsmcontext_init(&scaff, ctx, len, 0);
+ security_release_secctx(&scaff);
return 0;
error_path:
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index c7aa39bda5cc..9fab0e7d90c3 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -943,6 +943,7 @@ static int audit_log_pid_context(struct audit_context *context, pid_t pid,
struct lsmblob *blob, char *comm)
{
struct audit_buffer *ab;
+ struct lsmcontext lsmcxt;
char *ctx = NULL;
u32 len;
int rc = 0;
@@ -960,7 +961,8 @@ static int audit_log_pid_context(struct audit_context *context, pid_t pid,
rc = 1;
} else {
audit_log_format(ab, " obj=%s", ctx);
- security_release_secctx(ctx, len);
+ lsmcontext_init(&lsmcxt, ctx, len, 0); /*scaffolding*/
+ security_release_secctx(&lsmcxt);
}
}
audit_log_format(ab, " ocomm=");
@@ -1172,6 +1174,7 @@ static void audit_log_fcaps(struct audit_buffer *ab, struct audit_names *name)
static void show_special(struct audit_context *context, int *call_panic)
{
+ struct lsmcontext lsmcxt;
struct audit_buffer *ab;
int i;
@@ -1205,7 +1208,8 @@ static void show_special(struct audit_context *context, int *call_panic)
*call_panic = 1;
} else {
audit_log_format(ab, " obj=%s", ctx);
- security_release_secctx(ctx, len);
+ lsmcontext_init(&lsmcxt, ctx, len, 0);
+ security_release_secctx(&lsmcxt);
}
}
if (context->ipc.has_perm) {
@@ -1352,6 +1356,7 @@ static void audit_log_name(struct audit_context *context, struct audit_names *n,
char *ctx = NULL;
u32 len;
struct lsmblob blob;
+ struct lsmcontext lsmcxt;
lsmblob_init(&blob, n->osid);
if (security_secid_to_secctx(&blob, &ctx, &len)) {
@@ -1360,7 +1365,8 @@ static void audit_log_name(struct audit_context *context, struct audit_names *n,
*call_panic = 2;
} else {
audit_log_format(ab, " obj=%s", ctx);
- security_release_secctx(ctx, len);
+ lsmcontext_init(&lsmcxt, ctx, len, 0); /* scaffolding */
+ security_release_secctx(&lsmcxt);
}
}
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index e05f4ef68bd8..7834c357b60b 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -130,6 +130,7 @@ static void ip_cmsg_recv_checksum(struct msghdr *msg, struct sk_buff *skb,
static void ip_cmsg_recv_security(struct msghdr *msg, struct sk_buff *skb)
{
+ struct lsmcontext context;
struct lsmblob lb;
char *secdata;
u32 seclen;
@@ -144,7 +145,8 @@ static void ip_cmsg_recv_security(struct msghdr *msg, struct sk_buff *skb)
return;
put_cmsg(msg, SOL_IP, SCM_SECURITY, seclen, secdata);
- security_release_secctx(secdata, seclen);
+ lsmcontext_init(&context, secdata, seclen, 0); /* scaffolding */
+ security_release_secctx(&context);
}
static void ip_cmsg_recv_dstaddr(struct msghdr *msg, struct sk_buff *skb)
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index ca0968f13240..6954e6600583 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -331,6 +331,7 @@ static int ctnetlink_dump_secctx(struct sk_buff *skb, const struct nf_conn *ct)
int len, ret;
char *secctx;
struct lsmblob blob;
+ struct lsmcontext context;
lsmblob_init(&blob, ct->secmark);
ret = security_secid_to_secctx(&blob, &secctx, &len);
@@ -348,7 +349,8 @@ static int ctnetlink_dump_secctx(struct sk_buff *skb, const struct nf_conn *ct)
ret = 0;
nla_put_failure:
- security_release_secctx(secctx, len);
+ lsmcontext_init(&context, secctx, len, 0); /* scaffolding */
+ security_release_secctx(&context);
return ret;
}
#else
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index c793103f3cd7..79158ad0486e 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -176,6 +176,7 @@ static void ct_show_secctx(struct seq_file *s, const struct nf_conn *ct)
u32 len;
char *secctx;
struct lsmblob blob;
+ struct lsmcontext context;
lsmblob_init(&blob, ct->secmark);
ret = security_secid_to_secctx(&blob, &secctx, &len);
@@ -184,7 +185,8 @@ static void ct_show_secctx(struct seq_file *s, const struct nf_conn *ct)
seq_printf(s, "secctx=%s ", secctx);
- security_release_secctx(secctx, len);
+ lsmcontext_init(&context, secctx, len, 0); /* scaffolding */
+ security_release_secctx(&context);
}
#else
static inline void ct_show_secctx(struct seq_file *s, const struct nf_conn *ct)
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index 59211bff90ab..fe8403ef4e89 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -399,6 +399,7 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
enum ip_conntrack_info uninitialized_var(ctinfo);
struct nfnl_ct_hook *nfnl_ct;
bool csum_verify;
+ struct lsmcontext scaff; /* scaffolding */
char *secdata = NULL;
u32 seclen = 0;
@@ -629,8 +630,10 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
}
nlh->nlmsg_len = skb->len;
- if (seclen)
- security_release_secctx(secdata, seclen);
+ if (seclen) {
+ lsmcontext_init(&scaff, secdata, seclen, 0);
+ security_release_secctx(&scaff);
+ }
return skb;
nla_put_failure:
@@ -638,8 +641,10 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
kfree_skb(skb);
net_err_ratelimited("nf_queue: error creating packet message\n");
nlmsg_failure:
- if (seclen)
- security_release_secctx(secdata, seclen);
+ if (seclen) {
+ lsmcontext_init(&scaff, secdata, seclen, 0);
+ security_release_secctx(&scaff);
+ }
return NULL;
}
diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c
index 2294aa9471e6..15b1945853be 100644
--- a/net/netlabel/netlabel_unlabeled.c
+++ b/net/netlabel/netlabel_unlabeled.c
@@ -387,6 +387,7 @@ int netlbl_unlhsh_add(struct net *net,
struct net_device *dev;
struct netlbl_unlhsh_iface *iface;
struct audit_buffer *audit_buf = NULL;
+ struct lsmcontext context;
char *secctx = NULL;
u32 secctx_len;
struct lsmblob blob;
@@ -457,7 +458,9 @@ int netlbl_unlhsh_add(struct net *net,
&secctx,
&secctx_len) == 0) {
audit_log_format(audit_buf, " sec_obj=%s", secctx);
- security_release_secctx(secctx, secctx_len);
+ /* scaffolding */
+ lsmcontext_init(&context, secctx, secctx_len, 0);
+ security_release_secctx(&context);
}
audit_log_format(audit_buf, " res=%u", ret_val == 0 ? 1 : 0);
audit_log_end(audit_buf);
@@ -488,6 +491,7 @@ static int netlbl_unlhsh_remove_addr4(struct net *net,
struct netlbl_unlhsh_addr4 *entry;
struct audit_buffer *audit_buf;
struct net_device *dev;
+ struct lsmcontext context;
char *secctx;
u32 secctx_len;
struct lsmblob blob;
@@ -516,7 +520,9 @@ static int netlbl_unlhsh_remove_addr4(struct net *net,
security_secid_to_secctx(&blob,
&secctx, &secctx_len) == 0) {
audit_log_format(audit_buf, " sec_obj=%s", secctx);
- security_release_secctx(secctx, secctx_len);
+ /* scaffolding */
+ lsmcontext_init(&context, secctx, secctx_len, 0);
+ security_release_secctx(&context);
}
audit_log_format(audit_buf, " res=%u", entry != NULL ? 1 : 0);
audit_log_end(audit_buf);
@@ -553,6 +559,7 @@ static int netlbl_unlhsh_remove_addr6(struct net *net,
struct netlbl_unlhsh_addr6 *entry;
struct audit_buffer *audit_buf;
struct net_device *dev;
+ struct lsmcontext context;
char *secctx;
u32 secctx_len;
struct lsmblob blob;
@@ -580,7 +587,8 @@ static int netlbl_unlhsh_remove_addr6(struct net *net,
security_secid_to_secctx(&blob,
&secctx, &secctx_len) == 0) {
audit_log_format(audit_buf, " sec_obj=%s", secctx);
- security_release_secctx(secctx, secctx_len);
+ lsmcontext_init(&context, secctx, secctx_len, 0);
+ security_release_secctx(&context);
}
audit_log_format(audit_buf, " res=%u", entry != NULL ? 1 : 0);
audit_log_end(audit_buf);
@@ -1094,6 +1102,7 @@ static int netlbl_unlabel_staticlist_gen(u32 cmd,
int ret_val = -ENOMEM;
struct netlbl_unlhsh_walk_arg *cb_arg = arg;
struct net_device *dev;
+ struct lsmcontext context;
void *data;
u32 secid;
char *secctx;
@@ -1161,7 +1170,9 @@ static int netlbl_unlabel_staticlist_gen(u32 cmd,
NLBL_UNLABEL_A_SECCTX,
secctx_len,
secctx);
- security_release_secctx(secctx, secctx_len);
+ /* scaffolding */
+ lsmcontext_init(&context, secctx, secctx_len, 0);
+ security_release_secctx(&context);
if (ret_val != 0)
goto list_cb_failure;
diff --git a/net/netlabel/netlabel_user.c b/net/netlabel/netlabel_user.c
index 2ccc6567e2a2..94aea4985b74 100644
--- a/net/netlabel/netlabel_user.c
+++ b/net/netlabel/netlabel_user.c
@@ -98,6 +98,7 @@ struct audit_buffer *netlbl_audit_start_common(int type,
struct netlbl_audit *audit_info)
{
struct audit_buffer *audit_buf;
+ struct lsmcontext context;
char *secctx;
u32 secctx_len;
struct lsmblob blob;
@@ -117,7 +118,8 @@ struct audit_buffer *netlbl_audit_start_common(int type,
if (audit_info->secid != 0 &&
security_secid_to_secctx(&blob, &secctx, &secctx_len) == 0) {
audit_log_format(audit_buf, " subj=%s", secctx);
- security_release_secctx(secctx, secctx_len);
+ lsmcontext_init(&context, secctx, secctx_len, 0);/*scaffolding*/
+ security_release_secctx(&context);
}
return audit_buf;
diff --git a/security/security.c b/security/security.c
index 82e29c477fa4..3563b1e2f8f9 100644
--- a/security/security.c
+++ b/security/security.c
@@ -2116,17 +2116,19 @@ int security_secctx_to_secid(const char *secdata, u32 seclen,
}
EXPORT_SYMBOL(security_secctx_to_secid);
-void security_release_secctx(char *secdata, u32 seclen)
+void security_release_secctx(struct lsmcontext *cp)
{
struct security_hook_list *hp;
- int *display = current->security;
hlist_for_each_entry(hp, &security_hook_heads.release_secctx, list)
- if (*display == LSMBLOB_INVALID ||
- *display == hp->lsmid->slot) {
- hp->hook.release_secctx(secdata, seclen);
+ if (cp->slot == hp->lsmid->slot) {
+ hp->hook.release_secctx(cp->context, cp->len);
+ memset(cp, 0, sizeof(*cp));
return;
}
+
+ pr_warn("%s context \"%s\" from slot %d not released\n", __func__,
+ cp->context, cp->slot);
}
EXPORT_SYMBOL(security_release_secctx);
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index ad646b865295..3d571c438dfa 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -4439,11 +4439,16 @@ static int smack_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
return 0;
}
-/*
- * There used to be a smack_release_secctx hook
- * that did nothing back when hooks were in a vector.
- * Now that there's a list such a hook adds cost.
+/**
+ * smack_release_secctx - do everything necessary to free a context
+ * @secdata: Unused
+ * @seclen: Unused
+ *
+ * Do nothing but hold a slot in the hooks list.
*/
+static void smack_release_secctx(char *secdata, u32 seclen)
+{
+}
static int smack_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen)
{
@@ -4685,6 +4690,7 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT(ismaclabel, smack_ismaclabel),
LSM_HOOK_INIT(secid_to_secctx, smack_secid_to_secctx),
LSM_HOOK_INIT(secctx_to_secid, smack_secctx_to_secid),
+ LSM_HOOK_INIT(release_secctx, smack_release_secctx),
LSM_HOOK_INIT(inode_notifysecctx, smack_inode_notifysecctx),
LSM_HOOK_INIT(inode_setsecctx, smack_inode_setsecctx),
LSM_HOOK_INIT(inode_getsecctx, smack_inode_getsecctx),
--
2.20.1
^ permalink raw reply related
* [PATCH v4 15/23] LSM: Specify which LSM to display
From: Casey Schaufler @ 2019-06-26 19:22 UTC (permalink / raw)
To: casey.schaufler, jmorris, linux-security-module, selinux
Cc: casey, keescook, john.johansen, penguin-kernel, paul, sds
In-Reply-To: <20190626192234.11725-1-casey@schaufler-ca.com>
Create a new entry "display" in /proc/.../attr for controlling
which LSM security information is displayed for a process.
The name of an active LSM that supplies hooks for human readable
data may be written to "display" to set the value. The name of
the LSM currently in use can be read from "display".
At this point there can only be one LSM capable of display
active.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
fs/proc/base.c | 1 +
security/security.c | 129 ++++++++++++++++++++++++++++++++++++++------
2 files changed, 113 insertions(+), 17 deletions(-)
diff --git a/fs/proc/base.c b/fs/proc/base.c
index ddef482f1334..7bf70e041315 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -2618,6 +2618,7 @@ static const struct pid_entry attr_dir_stuff[] = {
ATTR(NULL, "fscreate", 0666),
ATTR(NULL, "keycreate", 0666),
ATTR(NULL, "sockcreate", 0666),
+ ATTR(NULL, "display", 0666),
#ifdef CONFIG_SECURITY_SMACK
DIR("smack", 0555,
proc_smack_attr_dir_inode_ops, proc_smack_attr_dir_ops),
diff --git a/security/security.c b/security/security.c
index 3180a6f30625..82e29c477fa4 100644
--- a/security/security.c
+++ b/security/security.c
@@ -46,7 +46,9 @@ static struct kmem_cache *lsm_file_cache;
static struct kmem_cache *lsm_inode_cache;
char *lsm_names;
-static struct lsm_blob_sizes blob_sizes __lsm_ro_after_init;
+static struct lsm_blob_sizes blob_sizes __lsm_ro_after_init = {
+ .lbs_task = sizeof(int), /* slot number for the "display" LSM */
+};
/* Boot-time LSM user choice */
static __initdata const char *chosen_lsm_order;
@@ -423,8 +425,10 @@ static int lsm_append(const char *new, char **result)
/*
* Current index to use while initializing the lsmblob secid list.
+ * Pointers to the LSM id structures for local use.
*/
static int lsm_slot;
+static struct lsm_id *lsm_slotlist[LSMBLOB_ENTRIES];
/**
* security_add_hooks - Add a modules hooks to the hook lists.
@@ -444,6 +448,7 @@ void __init security_add_hooks(struct security_hook_list *hooks, int count,
if (lsmid->slot == LSMBLOB_NEEDED) {
if (lsm_slot >= LSMBLOB_ENTRIES)
panic("%s Too many LSMs registered.\n", __func__);
+ lsm_slotlist[lsm_slot] = lsmid;
lsmid->slot = lsm_slot++;
init_debug("%s assigned lsmblob slot %d\n", lsmid->lsm,
lsmid->slot);
@@ -564,6 +569,8 @@ int lsm_inode_alloc(struct inode *inode)
*/
static int lsm_task_alloc(struct task_struct *task)
{
+ int *display;
+
if (blob_sizes.lbs_task == 0) {
task->security = NULL;
return 0;
@@ -572,6 +579,15 @@ static int lsm_task_alloc(struct task_struct *task)
task->security = kzalloc(blob_sizes.lbs_task, GFP_KERNEL);
if (task->security == NULL)
return -ENOMEM;
+
+ /*
+ * The start of the task blob contains the "display" LSM slot number.
+ * Start with it set to the invalid slot number, indicating that the
+ * default first registered LSM be displayed.
+ */
+ display = task->security;
+ *display = LSMBLOB_INVALID;
+
return 0;
}
@@ -1563,14 +1579,24 @@ int security_file_open(struct file *file)
int security_task_alloc(struct task_struct *task, unsigned long clone_flags)
{
+ int *odisplay = current->security;
+ int *ndisplay;
int rc = lsm_task_alloc(task);
- if (rc)
+ if (unlikely(rc))
return rc;
+
rc = call_int_hook(task_alloc, 0, task, clone_flags);
- if (unlikely(rc))
+ if (unlikely(rc)) {
security_task_free(task);
- return rc;
+ return rc;
+ }
+
+ ndisplay = task->security;
+ if (ndisplay && odisplay)
+ *ndisplay = *odisplay;
+
+ return 0;
}
void security_task_free(struct task_struct *task)
@@ -1967,10 +1993,29 @@ int security_getprocattr(struct task_struct *p, const char *lsm, char *name,
char **value)
{
struct security_hook_list *hp;
+ int *display = current->security;
+ int slot = 0;
+
+ if (!strcmp(name, "display")) {
+ /*
+ * lsm_slot will be 0 if there are no displaying modules.
+ */
+ if (lsm_slot == 0)
+ return -EINVAL;
+ if (*display != LSMBLOB_INVALID)
+ slot = *display;
+ *value = kstrdup(lsm_slotlist[slot]->lsm, GFP_KERNEL);
+ if (*value)
+ return strlen(*value);
+ return -ENOMEM;
+ }
hlist_for_each_entry(hp, &security_hook_heads.getprocattr, list) {
if (lsm != NULL && strcmp(lsm, hp->lsmid->lsm))
continue;
+ if (lsm == NULL && *display != LSMBLOB_INVALID &&
+ *display != hp->lsmid->slot)
+ continue;
return hp->hook.getprocattr(p, name, value);
}
return -EINVAL;
@@ -1980,10 +2025,46 @@ int security_setprocattr(const char *lsm, const char *name, void *value,
size_t size)
{
struct security_hook_list *hp;
+ char *term;
+ char *cp;
+ int *display = current->security;
+ int rc = -EINVAL;
+ int slot = 0;
+
+ if (!strcmp(name, "display")) {
+ /*
+ * lsm_slot will be 0 if there are no displaying modules.
+ */
+ if (lsm_slot == 0 || size == 0)
+ return -EINVAL;
+ cp = kzalloc(size + 1, GFP_KERNEL);
+ if (cp == NULL)
+ return -ENOMEM;
+ memcpy(cp, value, size);
+
+ term = strchr(cp, ' ');
+ if (term == NULL)
+ term = strchr(cp, '\n');
+ if (term != NULL)
+ *term = '\0';
+
+ for (slot = 0; slot < lsm_slot; slot++)
+ if (!strcmp(cp, lsm_slotlist[slot]->lsm)) {
+ *display = lsm_slotlist[slot]->slot;
+ rc = size;
+ break;
+ }
+
+ kfree(cp);
+ return rc;
+ }
hlist_for_each_entry(hp, &security_hook_heads.setprocattr, list) {
if (lsm != NULL && strcmp(lsm, hp->lsmid->lsm))
continue;
+ if (lsm == NULL && *display != LSMBLOB_INVALID &&
+ *display != hp->lsmid->slot)
+ continue;
return hp->hook.setprocattr(name, value, size);
}
return -EINVAL;
@@ -2003,15 +2084,15 @@ EXPORT_SYMBOL(security_ismaclabel);
int security_secid_to_secctx(struct lsmblob *blob, char **secdata, u32 *seclen)
{
struct security_hook_list *hp;
- int rc;
+ int *display = current->security;
hlist_for_each_entry(hp, &security_hook_heads.secid_to_secctx, list) {
if (WARN_ON(hp->lsmid->slot < 0 || hp->lsmid->slot >= lsm_slot))
continue;
- rc = hp->hook.secid_to_secctx(blob->secid[hp->lsmid->slot],
- secdata, seclen);
- if (rc != 0)
- return rc;
+ if (*display == LSMBLOB_INVALID || *display == hp->lsmid->slot)
+ return hp->hook.secid_to_secctx(
+ blob->secid[hp->lsmid->slot],
+ secdata, seclen);
}
return 0;
}
@@ -2021,16 +2102,15 @@ int security_secctx_to_secid(const char *secdata, u32 seclen,
struct lsmblob *blob)
{
struct security_hook_list *hp;
- int rc;
+ int *display = current->security;
lsmblob_init(blob, 0);
hlist_for_each_entry(hp, &security_hook_heads.secctx_to_secid, list) {
if (WARN_ON(hp->lsmid->slot < 0 || hp->lsmid->slot >= lsm_slot))
continue;
- rc = hp->hook.secctx_to_secid(secdata, seclen,
- &blob->secid[hp->lsmid->slot]);
- if (rc != 0)
- return rc;
+ if (*display == LSMBLOB_INVALID || *display == hp->lsmid->slot)
+ return hp->hook.secctx_to_secid(secdata, seclen,
+ &blob->secid[hp->lsmid->slot]);
}
return 0;
}
@@ -2038,7 +2118,15 @@ EXPORT_SYMBOL(security_secctx_to_secid);
void security_release_secctx(char *secdata, u32 seclen)
{
- call_void_hook(release_secctx, secdata, seclen);
+ struct security_hook_list *hp;
+ int *display = current->security;
+
+ hlist_for_each_entry(hp, &security_hook_heads.release_secctx, list)
+ if (*display == LSMBLOB_INVALID ||
+ *display == hp->lsmid->slot) {
+ hp->hook.release_secctx(secdata, seclen);
+ return;
+ }
}
EXPORT_SYMBOL(security_release_secctx);
@@ -2163,8 +2251,15 @@ EXPORT_SYMBOL(security_sock_rcv_skb);
int security_socket_getpeersec_stream(struct socket *sock, char __user *optval,
int __user *optlen, unsigned len)
{
- return call_int_hook(socket_getpeersec_stream, -ENOPROTOOPT, sock,
- optval, optlen, len);
+ int *display = current->security;
+ struct security_hook_list *hp;
+
+ hlist_for_each_entry(hp, &security_hook_heads.socket_getpeersec_stream,
+ list)
+ if (*display == LSMBLOB_INVALID || *display == hp->lsmid->slot)
+ return hp->hook.socket_getpeersec_stream(sock, optval,
+ optlen, len);
+ return -ENOPROTOOPT;
}
int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb,
--
2.20.1
^ permalink raw reply related
* [PATCH v4 14/23] IMA: Change internal interfaces to use lsmblobs
From: Casey Schaufler @ 2019-06-26 19:22 UTC (permalink / raw)
To: casey.schaufler, jmorris, linux-security-module, selinux
Cc: casey, keescook, john.johansen, penguin-kernel, paul, sds
In-Reply-To: <20190626192234.11725-1-casey@schaufler-ca.com>
The IMA interfaces ima_get_action() and ima_match_policy()
call LSM functions that use lsmblobs. Change the IMA functions
to pass the lsmblob to be compatible with the LSM functions.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
security/integrity/ima/ima.h | 10 ++++++----
security/integrity/ima/ima_api.c | 9 +++++----
security/integrity/ima/ima_appraise.c | 4 +---
security/integrity/ima/ima_main.c | 27 +++++++++++----------------
security/integrity/ima/ima_policy.c | 12 ++++++------
5 files changed, 29 insertions(+), 33 deletions(-)
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 5a337239d9e4..73b3b15dec5c 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -192,8 +192,9 @@ enum ima_hooks {
};
/* LIM API function definitions */
-int ima_get_action(struct inode *inode, const struct cred *cred, u32 secid,
- int mask, enum ima_hooks func, int *pcr);
+int ima_get_action(struct inode *inode, const struct cred *cred,
+ struct lsmblob *blob, int mask, enum ima_hooks func,
+ int *pcr);
int ima_must_measure(struct inode *inode, int mask, enum ima_hooks func);
int ima_collect_measurement(struct integrity_iint_cache *iint,
struct file *file, void *buf, loff_t size,
@@ -213,8 +214,9 @@ void ima_free_template_entry(struct ima_template_entry *entry);
const char *ima_d_path(const struct path *path, char **pathbuf, char *filename);
/* IMA policy related functions */
-int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid,
- enum ima_hooks func, int mask, int flags, int *pcr);
+int ima_match_policy(struct inode *inode, const struct cred *cred,
+ struct lsmblob *blob, enum ima_hooks func, int mask,
+ int flags, int *pcr);
void ima_init_policy(void);
void ima_update_policy(void);
void ima_update_policy_flag(void);
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index c7505fb122d4..94b2a4840d81 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -159,7 +159,7 @@ void ima_add_violation(struct file *file, const unsigned char *filename,
* ima_get_action - appraise & measure decision based on policy.
* @inode: pointer to inode to measure
* @cred: pointer to credentials structure to validate
- * @secid: secid of the task being validated
+ * @blob: LSM data of the task being validated
* @mask: contains the permission mask (MAY_READ, MAY_WRITE, MAY_EXEC,
* MAY_APPEND)
* @func: caller identifier
@@ -175,14 +175,15 @@ void ima_add_violation(struct file *file, const unsigned char *filename,
* Returns IMA_MEASURE, IMA_APPRAISE mask.
*
*/
-int ima_get_action(struct inode *inode, const struct cred *cred, u32 secid,
- int mask, enum ima_hooks func, int *pcr)
+int ima_get_action(struct inode *inode, const struct cred *cred,
+ struct lsmblob *blob, int mask, enum ima_hooks func,
+ int *pcr)
{
int flags = IMA_MEASURE | IMA_AUDIT | IMA_APPRAISE | IMA_HASH;
flags &= ima_policy_flag;
- return ima_match_policy(inode, cred, secid, func, mask, flags, pcr);
+ return ima_match_policy(inode, cred, blob, func, mask, flags, pcr);
}
/*
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
index 85c7692fc4a3..3ff7aae81829 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -50,15 +50,13 @@ bool is_ima_appraise_enabled(void)
*/
int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func)
{
- u32 secid;
struct lsmblob blob;
if (!ima_appraise)
return 0;
security_task_getsecid(current, &blob);
- lsmblob_secid(&blob, &secid);
- return ima_match_policy(inode, current_cred(), secid, func, mask,
+ return ima_match_policy(inode, current_cred(), &blob, func, mask,
IMA_APPRAISE | IMA_HASH, NULL);
}
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 1afb75a893af..0588dd9a88db 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -169,8 +169,8 @@ void ima_file_free(struct file *file)
}
static int process_measurement(struct file *file, const struct cred *cred,
- u32 secid, char *buf, loff_t size, int mask,
- enum ima_hooks func)
+ struct lsmblob *blob, char *buf, loff_t size,
+ int mask, enum ima_hooks func)
{
struct inode *inode = file_inode(file);
struct integrity_iint_cache *iint = NULL;
@@ -192,7 +192,7 @@ static int process_measurement(struct file *file, const struct cred *cred,
* bitmask based on the appraise/audit/measurement policy.
* Included is the appraise submask.
*/
- action = ima_get_action(inode, cred, secid, mask, func, &pcr);
+ action = ima_get_action(inode, cred, blob, mask, func, &pcr);
violation_check = ((func == FILE_CHECK || func == MMAP_CHECK) &&
(ima_policy_flag & IMA_MEASURE));
if (!action && !violation_check)
@@ -339,8 +339,7 @@ int ima_file_mmap(struct file *file, unsigned long prot)
if (file && (prot & PROT_EXEC)) {
security_task_getsecid(current, &blob);
- /* scaffolding - until process_measurement changes */
- return process_measurement(file, current_cred(), blob.secid[0],
+ return process_measurement(file, current_cred(), &blob,
NULL, 0, MAY_EXEC, MMAP_CHECK);
}
@@ -366,16 +365,14 @@ int ima_bprm_check(struct linux_binprm *bprm)
struct lsmblob blob;
security_task_getsecid(current, &blob);
- /* scaffolding until process_measurement changes */
- ret = process_measurement(bprm->file, current_cred(), blob.secid[0],
- NULL, 0, MAY_EXEC, BPRM_CHECK);
+ ret = process_measurement(bprm->file, current_cred(), &blob, NULL, 0,
+ MAY_EXEC, BPRM_CHECK);
if (ret)
return ret;
security_cred_getsecid(bprm->cred, &blob);
- /* scaffolding until process_measurement changes */
- return process_measurement(bprm->file, bprm->cred, blob.secid[0],
- NULL, 0, MAY_EXEC, CREDS_CHECK);
+ return process_measurement(bprm->file, bprm->cred, &blob, NULL, 0,
+ MAY_EXEC, CREDS_CHECK);
}
/**
@@ -393,8 +390,7 @@ int ima_file_check(struct file *file, int mask)
struct lsmblob blob;
security_task_getsecid(current, &blob);
- /* scaffolding until process_measurement changes */
- return process_measurement(file, current_cred(), blob.secid[0], NULL, 0,
+ return process_measurement(file, current_cred(), &blob, NULL, 0,
mask & (MAY_READ | MAY_WRITE | MAY_EXEC |
MAY_APPEND), FILE_CHECK);
}
@@ -526,9 +522,8 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size,
func = read_idmap[read_id] ?: FILE_CHECK;
security_task_getsecid(current, &blob);
- /* scaffolding until process_measurement changes */
- return process_measurement(file, current_cred(), blob.secid[0], buf,
- size, MAY_READ, func);
+ return process_measurement(file, current_cred(), &blob, buf, size,
+ MAY_READ, func);
}
/**
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index 92ee3d984c73..dbad256aa7b4 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -286,7 +286,7 @@ static void ima_lsm_update_rules(void)
* Returns true on rule match, false on failure.
*/
static bool ima_match_rules(struct ima_rule_entry *rule, struct inode *inode,
- const struct cred *cred, u32 secid,
+ const struct cred *cred, struct lsmblob *blob,
enum ima_hooks func, int mask)
{
int i;
@@ -345,7 +345,6 @@ static bool ima_match_rules(struct ima_rule_entry *rule, struct inode *inode,
case LSM_SUBJ_USER:
case LSM_SUBJ_ROLE:
case LSM_SUBJ_TYPE:
- lsmblob_init(&blob, secid);
rc = security_filter_rule_match(&blob,
rule->lsm[i].type,
Audit_equal,
@@ -394,7 +393,7 @@ static int get_subaction(struct ima_rule_entry *rule, enum ima_hooks func)
* @inode: pointer to an inode for which the policy decision is being made
* @cred: pointer to a credentials structure for which the policy decision is
* being made
- * @secid: LSM secid of the task to be validated
+ * @blob: LSM data of the task to be validated
* @func: IMA hook identifier
* @mask: requested action (MAY_READ | MAY_WRITE | MAY_APPEND | MAY_EXEC)
* @pcr: set the pcr to extend
@@ -406,8 +405,9 @@ static int get_subaction(struct ima_rule_entry *rule, enum ima_hooks func)
* list when walking it. Reads are many orders of magnitude more numerous
* than writes so ima_match_policy() is classical RCU candidate.
*/
-int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid,
- enum ima_hooks func, int mask, int flags, int *pcr)
+int ima_match_policy(struct inode *inode, const struct cred *cred,
+ struct lsmblob *blob, enum ima_hooks func, int mask,
+ int flags, int *pcr)
{
struct ima_rule_entry *entry;
int action = 0, actmask = flags | (flags << 1);
@@ -418,7 +418,7 @@ int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid,
if (!(entry->action & actmask))
continue;
- if (!ima_match_rules(entry, inode, cred, secid, func, mask))
+ if (!ima_match_rules(entry, inode, cred, blob, func, mask))
continue;
action |= entry->flags & IMA_ACTION_FLAGS;
--
2.20.1
^ permalink raw reply related
* [PATCH v4 13/23] LSM: Use lsmblob in security_cred_getsecid
From: Casey Schaufler @ 2019-06-26 19:22 UTC (permalink / raw)
To: casey.schaufler, jmorris, linux-security-module, selinux
Cc: casey, keescook, john.johansen, penguin-kernel, paul, sds
In-Reply-To: <20190626192234.11725-1-casey@schaufler-ca.com>
Change the security_cred_getsecid() interface to fill in a
lsmblob instead of a u32 secid. The associated data elements
in the audit sub-system are changed from a secid to a lsmblob
to accomodate multiple possible LSM audit users.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
include/linux/security.h | 2 +-
kernel/audit.c | 14 +++++-------
kernel/audit.h | 5 +++--
kernel/auditsc.c | 37 +++++++++++--------------------
security/integrity/ima/ima_main.c | 8 +++----
security/security.c | 12 +++++++---
6 files changed, 36 insertions(+), 42 deletions(-)
diff --git a/include/linux/security.h b/include/linux/security.h
index 2d81cac418e3..d310fa3942ce 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -387,7 +387,7 @@ int security_cred_alloc_blank(struct cred *cred, gfp_t gfp);
void security_cred_free(struct cred *cred);
int security_prepare_creds(struct cred *new, const struct cred *old, gfp_t gfp);
void security_transfer_creds(struct cred *new, const struct cred *old);
-void security_cred_getsecid(const struct cred *c, u32 *secid);
+void security_cred_getsecid(const struct cred *c, struct lsmblob *blob);
int security_kernel_act_as(struct cred *new, struct lsmblob *blob);
int security_kernel_create_files_as(struct cred *new, struct inode *inode);
int security_kernel_module_request(char *kmod_name);
diff --git a/kernel/audit.c b/kernel/audit.c
index a0205f3c23c7..1b51e907f131 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -137,7 +137,7 @@ static u32 audit_backlog_wait_time = AUDIT_BACKLOG_WAIT_TIME;
/* The identity of the user shutting down the audit system. */
kuid_t audit_sig_uid = INVALID_UID;
pid_t audit_sig_pid = -1;
-u32 audit_sig_sid = 0;
+struct lsmblob audit_sig_lsm;
/* Records can be lost in several ways:
0) [suppressed in audit_alloc]
@@ -1429,23 +1429,21 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
}
case AUDIT_SIGNAL_INFO:
len = 0;
- if (audit_sig_sid) {
- struct lsmblob blob;
-
- lsmblob_init(&blob, audit_sig_sid);
- err = security_secid_to_secctx(&blob, &ctx, &len);
+ if (lsmblob_is_set(&audit_sig_lsm)) {
+ err = security_secid_to_secctx(&audit_sig_lsm, &ctx,
+ &len);
if (err)
return err;
}
sig_data = kmalloc(sizeof(*sig_data) + len, GFP_KERNEL);
if (!sig_data) {
- if (audit_sig_sid)
+ if (lsmblob_is_set(&audit_sig_lsm))
security_release_secctx(ctx, len);
return -ENOMEM;
}
sig_data->uid = from_kuid(&init_user_ns, audit_sig_uid);
sig_data->pid = audit_sig_pid;
- if (audit_sig_sid) {
+ if (lsmblob_is_set(&audit_sig_lsm)) {
memcpy(sig_data->ctx, ctx, len);
security_release_secctx(ctx, len);
}
diff --git a/kernel/audit.h b/kernel/audit.h
index 958d5b8fc1b3..29e29c6f4afb 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -22,6 +22,7 @@
#include <linux/fs.h>
#include <linux/audit.h>
#include <linux/skbuff.h>
+#include <linux/security.h>
#include <uapi/linux/mqueue.h>
#include <linux/tty.h>
@@ -147,7 +148,7 @@ struct audit_context {
kuid_t target_auid;
kuid_t target_uid;
unsigned int target_sessionid;
- u32 target_sid;
+ struct lsmblob target_lsm;
char target_comm[TASK_COMM_LEN];
struct audit_tree_refs *trees, *first_trees;
@@ -338,7 +339,7 @@ extern char *audit_unpack_string(void **bufp, size_t *remain, size_t len);
extern pid_t audit_sig_pid;
extern kuid_t audit_sig_uid;
-extern u32 audit_sig_sid;
+extern struct lsmblob audit_sig_lsm;
extern int audit_filter(int msgtype, unsigned int listtype);
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 54797c0fc3b7..c7aa39bda5cc 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -112,7 +112,7 @@ struct audit_aux_data_pids {
kuid_t target_auid[AUDIT_AUX_PIDS];
kuid_t target_uid[AUDIT_AUX_PIDS];
unsigned int target_sessionid[AUDIT_AUX_PIDS];
- u32 target_sid[AUDIT_AUX_PIDS];
+ struct lsmblob target_lsm[AUDIT_AUX_PIDS];
char target_comm[AUDIT_AUX_PIDS][TASK_COMM_LEN];
int pid_count;
};
@@ -938,14 +938,14 @@ static inline void audit_free_context(struct audit_context *context)
}
static int audit_log_pid_context(struct audit_context *context, pid_t pid,
- kuid_t auid, kuid_t uid, unsigned int sessionid,
- u32 sid, char *comm)
+ kuid_t auid, kuid_t uid,
+ unsigned int sessionid,
+ struct lsmblob *blob, char *comm)
{
struct audit_buffer *ab;
char *ctx = NULL;
u32 len;
int rc = 0;
- struct lsmblob blob;
ab = audit_log_start(context, GFP_KERNEL, AUDIT_OBJ_PID);
if (!ab)
@@ -954,9 +954,8 @@ static int audit_log_pid_context(struct audit_context *context, pid_t pid,
audit_log_format(ab, "opid=%d oauid=%d ouid=%d oses=%d", pid,
from_kuid(&init_user_ns, auid),
from_kuid(&init_user_ns, uid), sessionid);
- if (sid) {
- lsmblob_init(&blob, sid);
- if (security_secid_to_secctx(&blob, &ctx, &len)) {
+ if (lsmblob_is_set(blob)) {
+ if (security_secid_to_secctx(blob, &ctx, &len)) {
audit_log_format(ab, " obj=(none)");
rc = 1;
} else {
@@ -1527,7 +1526,7 @@ static void audit_log_exit(void)
axs->target_auid[i],
axs->target_uid[i],
axs->target_sessionid[i],
- axs->target_sid[i],
+ &axs->target_lsm[i],
axs->target_comm[i]))
call_panic = 1;
}
@@ -1536,7 +1535,7 @@ static void audit_log_exit(void)
audit_log_pid_context(context, context->target_pid,
context->target_auid, context->target_uid,
context->target_sessionid,
- context->target_sid, context->target_comm))
+ &context->target_lsm, context->target_comm))
call_panic = 1;
if (context->pwd.dentry && context->pwd.mnt) {
@@ -1713,7 +1712,7 @@ void __audit_syscall_exit(int success, long return_code)
context->aux = NULL;
context->aux_pids = NULL;
context->target_pid = 0;
- context->target_sid = 0;
+ lsmblob_init(&context->target_lsm, 0);
context->sockaddr_len = 0;
context->type = 0;
context->fds[0] = -1;
@@ -2367,15 +2366,12 @@ int __audit_sockaddr(int len, void *a)
void __audit_ptrace(struct task_struct *t)
{
struct audit_context *context = audit_context();
- struct lsmblob blob;
context->target_pid = task_tgid_nr(t);
context->target_auid = audit_get_loginuid(t);
context->target_uid = task_uid(t);
context->target_sessionid = audit_get_sessionid(t);
- security_task_getsecid(t, &blob);
- /* scaffolding - until target_sid is converted */
- context->target_sid = blob.secid[0];
+ security_task_getsecid(t, &context->target_lsm);
memcpy(context->target_comm, t->comm, TASK_COMM_LEN);
}
@@ -2392,7 +2388,6 @@ int audit_signal_info(int sig, struct task_struct *t)
struct audit_aux_data_pids *axp;
struct audit_context *ctx = audit_context();
kuid_t uid = current_uid(), auid, t_uid = task_uid(t);
- struct lsmblob blob;
if (auditd_test_task(t) &&
(sig == SIGTERM || sig == SIGHUP ||
@@ -2403,9 +2398,7 @@ int audit_signal_info(int sig, struct task_struct *t)
audit_sig_uid = auid;
else
audit_sig_uid = uid;
- security_task_getsecid(current, &blob);
- /* scaffolding until audit_sig_sid is converted */
- audit_sig_sid = blob.secid[0];
+ security_task_getsecid(current, &audit_sig_lsm);
}
if (!audit_signals || audit_dummy_context())
@@ -2418,9 +2411,7 @@ int audit_signal_info(int sig, struct task_struct *t)
ctx->target_auid = audit_get_loginuid(t);
ctx->target_uid = t_uid;
ctx->target_sessionid = audit_get_sessionid(t);
- security_task_getsecid(t, &blob);
- /* scaffolding until target_sid is converted */
- ctx->target_sid = blob.secid[0];
+ security_task_getsecid(t, &ctx->target_lsm);
memcpy(ctx->target_comm, t->comm, TASK_COMM_LEN);
return 0;
}
@@ -2441,9 +2432,7 @@ int audit_signal_info(int sig, struct task_struct *t)
axp->target_auid[axp->pid_count] = audit_get_loginuid(t);
axp->target_uid[axp->pid_count] = t_uid;
axp->target_sessionid[axp->pid_count] = audit_get_sessionid(t);
- security_task_getsecid(t, &blob);
- /* scaffolding until target_sid is converted */
- axp->target_sid[axp->pid_count] = blob.secid[0];
+ security_task_getsecid(t, &axp->target_lsm[axp->pid_count]);
memcpy(axp->target_comm[axp->pid_count], t->comm, TASK_COMM_LEN);
axp->pid_count++;
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index fefa848cf0c7..1afb75a893af 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -363,7 +363,6 @@ int ima_file_mmap(struct file *file, unsigned long prot)
int ima_bprm_check(struct linux_binprm *bprm)
{
int ret;
- u32 secid;
struct lsmblob blob;
security_task_getsecid(current, &blob);
@@ -373,9 +372,10 @@ int ima_bprm_check(struct linux_binprm *bprm)
if (ret)
return ret;
- security_cred_getsecid(bprm->cred, &secid);
- return process_measurement(bprm->file, bprm->cred, secid, NULL, 0,
- MAY_EXEC, CREDS_CHECK);
+ security_cred_getsecid(bprm->cred, &blob);
+ /* scaffolding until process_measurement changes */
+ return process_measurement(bprm->file, bprm->cred, blob.secid[0],
+ NULL, 0, MAY_EXEC, CREDS_CHECK);
}
/**
diff --git a/security/security.c b/security/security.c
index 91388553d3d7..3180a6f30625 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1627,10 +1627,16 @@ void security_transfer_creds(struct cred *new, const struct cred *old)
call_void_hook(cred_transfer, new, old);
}
-void security_cred_getsecid(const struct cred *c, u32 *secid)
+void security_cred_getsecid(const struct cred *c, struct lsmblob *blob)
{
- *secid = 0;
- call_void_hook(cred_getsecid, c, secid);
+ struct security_hook_list *hp;
+
+ lsmblob_init(blob, 0);
+ hlist_for_each_entry(hp, &security_hook_heads.cred_getsecid, list) {
+ if (WARN_ON(hp->lsmid->slot < 0 || hp->lsmid->slot >= lsm_slot))
+ continue;
+ hp->hook.cred_getsecid(c, &blob->secid[hp->lsmid->slot]);
+ }
}
EXPORT_SYMBOL(security_cred_getsecid);
--
2.20.1
^ permalink raw reply related
* [PATCH v4 11/23] LSM: Use lsmblob in security_task_getsecid
From: Casey Schaufler @ 2019-06-26 19:22 UTC (permalink / raw)
To: casey.schaufler, jmorris, linux-security-module, selinux
Cc: casey, keescook, john.johansen, penguin-kernel, paul, sds
In-Reply-To: <20190626192234.11725-1-casey@schaufler-ca.com>
Change the security_task_getsecid() interface to fill in
a lsmblob structure instead of a u32 secid in support of
LSM stacking. Audit interfaces will need to collect all
possible secids for possible reporting.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
drivers/android/binder.c | 4 +---
include/linux/security.h | 7 +++---
kernel/audit.c | 6 ++---
kernel/auditfilter.c | 4 +---
kernel/auditsc.c | 22 ++++++++++++------
net/netlabel/netlabel_unlabeled.c | 5 +++-
net/netlabel/netlabel_user.h | 6 ++++-
security/integrity/ima/ima_appraise.c | 4 +++-
security/integrity/ima/ima_main.c | 33 +++++++++++++++------------
security/security.c | 12 +++++++---
10 files changed, 63 insertions(+), 40 deletions(-)
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 1962f6b8abd0..144ac4f1c24f 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -3119,11 +3119,9 @@ static void binder_transaction(struct binder_proc *proc,
t->priority = task_nice(current);
if (target_node && target_node->txn_security_ctx) {
- u32 secid;
struct lsmblob blob;
- security_task_getsecid(proc->tsk, &secid);
- lsmblob_init(&blob, secid);
+ security_task_getsecid(proc->tsk, &blob);
ret = security_secid_to_secctx(&blob, &secctx, &secctx_sz);
if (ret) {
return_error = BR_FAILED_REPLY;
diff --git a/include/linux/security.h b/include/linux/security.h
index 41dc3053094e..cfd7cf4b0be9 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -400,7 +400,7 @@ int security_task_fix_setuid(struct cred *new, const struct cred *old,
int security_task_setpgid(struct task_struct *p, pid_t pgid);
int security_task_getpgid(struct task_struct *p);
int security_task_getsid(struct task_struct *p);
-void security_task_getsecid(struct task_struct *p, u32 *secid);
+void security_task_getsecid(struct task_struct *p, struct lsmblob *blob);
int security_task_setnice(struct task_struct *p, int nice);
int security_task_setioprio(struct task_struct *p, int ioprio);
int security_task_getioprio(struct task_struct *p);
@@ -1029,9 +1029,10 @@ static inline int security_task_getsid(struct task_struct *p)
return 0;
}
-static inline void security_task_getsecid(struct task_struct *p, u32 *secid)
+static inline void security_task_getsecid(struct task_struct *p,
+ struct lsmblob *blob)
{
- *secid = 0;
+ lsmblob_init(blob, 0);
}
static inline int security_task_setnice(struct task_struct *p, int nice)
diff --git a/kernel/audit.c b/kernel/audit.c
index d0338411d75d..a0205f3c23c7 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -2075,14 +2075,12 @@ int audit_log_task_context(struct audit_buffer *ab)
char *ctx = NULL;
unsigned len;
int error;
- u32 sid;
struct lsmblob blob;
- security_task_getsecid(current, &sid);
- if (!sid)
+ security_task_getsecid(current, &blob);
+ if (!lsmblob_is_set(&blob))
return 0;
- lsmblob_init(&blob, sid);
error = security_secid_to_secctx(&blob, &ctx, &len);
if (error) {
if (error != -EINVAL)
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index 8786b95b60bd..8f244c98bb57 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -1323,7 +1323,6 @@ int audit_filter(int msgtype, unsigned int listtype)
for (i = 0; i < e->rule.field_count; i++) {
struct audit_field *f = &e->rule.fields[i];
pid_t pid;
- u32 sid;
struct lsmblob blob;
switch (f->type) {
@@ -1354,8 +1353,7 @@ int audit_filter(int msgtype, unsigned int listtype)
case AUDIT_SUBJ_SEN:
case AUDIT_SUBJ_CLR:
if (f->lsm_rule) {
- security_task_getsecid(current, &sid);
- lsmblob_init(&blob, sid);
+ security_task_getsecid(current, &blob);
result = security_audit_rule_match(
&blob, f->type,
f->op, f->lsm_rule);
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 148733ec3c72..7112fe31684d 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -444,7 +444,6 @@ static int audit_filter_rules(struct task_struct *tsk,
{
const struct cred *cred;
int i, need_sid = 1;
- u32 sid;
struct lsmblob blob;
unsigned int sessionid;
@@ -628,10 +627,9 @@ static int audit_filter_rules(struct task_struct *tsk,
logged upon error */
if (f->lsm_rule) {
if (need_sid) {
- security_task_getsecid(tsk, &sid);
+ security_task_getsecid(tsk, &blob);
need_sid = 0;
}
- lsmblob_init(&blob, sid);
result = security_audit_rule_match(&blob,
f->type,
f->op,
@@ -2365,12 +2363,15 @@ int __audit_sockaddr(int len, void *a)
void __audit_ptrace(struct task_struct *t)
{
struct audit_context *context = audit_context();
+ struct lsmblob blob;
context->target_pid = task_tgid_nr(t);
context->target_auid = audit_get_loginuid(t);
context->target_uid = task_uid(t);
context->target_sessionid = audit_get_sessionid(t);
- security_task_getsecid(t, &context->target_sid);
+ security_task_getsecid(t, &blob);
+ /* scaffolding - until target_sid is converted */
+ context->target_sid = blob.secid[0];
memcpy(context->target_comm, t->comm, TASK_COMM_LEN);
}
@@ -2387,6 +2388,7 @@ int audit_signal_info(int sig, struct task_struct *t)
struct audit_aux_data_pids *axp;
struct audit_context *ctx = audit_context();
kuid_t uid = current_uid(), auid, t_uid = task_uid(t);
+ struct lsmblob blob;
if (auditd_test_task(t) &&
(sig == SIGTERM || sig == SIGHUP ||
@@ -2397,7 +2399,9 @@ int audit_signal_info(int sig, struct task_struct *t)
audit_sig_uid = auid;
else
audit_sig_uid = uid;
- security_task_getsecid(current, &audit_sig_sid);
+ security_task_getsecid(current, &blob);
+ /* scaffolding until audit_sig_sid is converted */
+ audit_sig_sid = blob.secid[0];
}
if (!audit_signals || audit_dummy_context())
@@ -2410,7 +2414,9 @@ int audit_signal_info(int sig, struct task_struct *t)
ctx->target_auid = audit_get_loginuid(t);
ctx->target_uid = t_uid;
ctx->target_sessionid = audit_get_sessionid(t);
- security_task_getsecid(t, &ctx->target_sid);
+ security_task_getsecid(t, &blob);
+ /* scaffolding until target_sid is converted */
+ ctx->target_sid = blob.secid[0];
memcpy(ctx->target_comm, t->comm, TASK_COMM_LEN);
return 0;
}
@@ -2431,7 +2437,9 @@ int audit_signal_info(int sig, struct task_struct *t)
axp->target_auid[axp->pid_count] = audit_get_loginuid(t);
axp->target_uid[axp->pid_count] = t_uid;
axp->target_sessionid[axp->pid_count] = audit_get_sessionid(t);
- security_task_getsecid(t, &axp->target_sid[axp->pid_count]);
+ security_task_getsecid(t, &blob);
+ /* scaffolding until target_sid is converted */
+ axp->target_sid[axp->pid_count] = blob.secid[0];
memcpy(axp->target_comm[axp->pid_count], t->comm, TASK_COMM_LEN);
axp->pid_count++;
diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c
index 2d8dd5b84457..2294aa9471e6 100644
--- a/net/netlabel/netlabel_unlabeled.c
+++ b/net/netlabel/netlabel_unlabeled.c
@@ -1552,11 +1552,14 @@ int __init netlbl_unlabel_defconf(void)
int ret_val;
struct netlbl_dom_map *entry;
struct netlbl_audit audit_info;
+ struct lsmblob blob;
/* Only the kernel is allowed to call this function and the only time
* it is called is at bootup before the audit subsystem is reporting
* messages so don't worry to much about these values. */
- security_task_getsecid(current, &audit_info.secid);
+ security_task_getsecid(current, &blob);
+ /* scaffolding until audit_info.secid is converted */
+ audit_info.secid = blob.secid[0];
audit_info.loginuid = GLOBAL_ROOT_UID;
audit_info.sessionid = 0;
diff --git a/net/netlabel/netlabel_user.h b/net/netlabel/netlabel_user.h
index 4a397cde1a48..ab88baaaa50d 100644
--- a/net/netlabel/netlabel_user.h
+++ b/net/netlabel/netlabel_user.h
@@ -48,7 +48,11 @@
static inline void netlbl_netlink_auditinfo(struct sk_buff *skb,
struct netlbl_audit *audit_info)
{
- security_task_getsecid(current, &audit_info->secid);
+ struct lsmblob blob;
+
+ security_task_getsecid(current, &blob);
+ /* scaffolding until secid is converted */
+ audit_info->secid = blob.secid[0];
audit_info->loginuid = audit_get_loginuid(current);
audit_info->sessionid = audit_get_sessionid(current);
}
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
index 5fb7127bbe68..85c7692fc4a3 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -51,11 +51,13 @@ bool is_ima_appraise_enabled(void)
int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func)
{
u32 secid;
+ struct lsmblob blob;
if (!ima_appraise)
return 0;
- security_task_getsecid(current, &secid);
+ security_task_getsecid(current, &blob);
+ lsmblob_secid(&blob, &secid);
return ima_match_policy(inode, current_cred(), secid, func, mask,
IMA_APPRAISE | IMA_HASH, NULL);
}
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 357edd140c09..fefa848cf0c7 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -335,12 +335,13 @@ static int process_measurement(struct file *file, const struct cred *cred,
*/
int ima_file_mmap(struct file *file, unsigned long prot)
{
- u32 secid;
+ struct lsmblob blob;
if (file && (prot & PROT_EXEC)) {
- security_task_getsecid(current, &secid);
- return process_measurement(file, current_cred(), secid, NULL,
- 0, MAY_EXEC, MMAP_CHECK);
+ security_task_getsecid(current, &blob);
+ /* scaffolding - until process_measurement changes */
+ return process_measurement(file, current_cred(), blob.secid[0],
+ NULL, 0, MAY_EXEC, MMAP_CHECK);
}
return 0;
@@ -363,10 +364,12 @@ int ima_bprm_check(struct linux_binprm *bprm)
{
int ret;
u32 secid;
+ struct lsmblob blob;
- security_task_getsecid(current, &secid);
- ret = process_measurement(bprm->file, current_cred(), secid, NULL, 0,
- MAY_EXEC, BPRM_CHECK);
+ security_task_getsecid(current, &blob);
+ /* scaffolding until process_measurement changes */
+ ret = process_measurement(bprm->file, current_cred(), blob.secid[0],
+ NULL, 0, MAY_EXEC, BPRM_CHECK);
if (ret)
return ret;
@@ -387,10 +390,11 @@ int ima_bprm_check(struct linux_binprm *bprm)
*/
int ima_file_check(struct file *file, int mask)
{
- u32 secid;
+ struct lsmblob blob;
- security_task_getsecid(current, &secid);
- return process_measurement(file, current_cred(), secid, NULL, 0,
+ security_task_getsecid(current, &blob);
+ /* scaffolding until process_measurement changes */
+ return process_measurement(file, current_cred(), blob.secid[0], NULL, 0,
mask & (MAY_READ | MAY_WRITE | MAY_EXEC |
MAY_APPEND), FILE_CHECK);
}
@@ -499,7 +503,7 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size,
enum kernel_read_file_id read_id)
{
enum ima_hooks func;
- u32 secid;
+ struct lsmblob blob;
if (!file && read_id == READING_FIRMWARE) {
if ((ima_appraise & IMA_APPRAISE_FIRMWARE) &&
@@ -521,9 +525,10 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size,
}
func = read_idmap[read_id] ?: FILE_CHECK;
- security_task_getsecid(current, &secid);
- return process_measurement(file, current_cred(), secid, buf, size,
- MAY_READ, func);
+ security_task_getsecid(current, &blob);
+ /* scaffolding until process_measurement changes */
+ return process_measurement(file, current_cred(), blob.secid[0], buf,
+ size, MAY_READ, func);
}
/**
diff --git a/security/security.c b/security/security.c
index 5245d4d1e799..2f123003b0b3 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1712,10 +1712,16 @@ int security_task_getsid(struct task_struct *p)
return call_int_hook(task_getsid, 0, p);
}
-void security_task_getsecid(struct task_struct *p, u32 *secid)
+void security_task_getsecid(struct task_struct *p, struct lsmblob *blob)
{
- *secid = 0;
- call_void_hook(task_getsecid, p, secid);
+ struct security_hook_list *hp;
+
+ lsmblob_init(blob, 0);
+ hlist_for_each_entry(hp, &security_hook_heads.task_getsecid, list) {
+ if (WARN_ON(hp->lsmid->slot < 0 || hp->lsmid->slot >= lsm_slot))
+ continue;
+ hp->hook.task_getsecid(p, &blob->secid[hp->lsmid->slot]);
+ }
}
EXPORT_SYMBOL(security_task_getsecid);
--
2.20.1
^ permalink raw reply related
* [PATCH v4 12/23] LSM: Use lsmblob in security_inode_getsecid
From: Casey Schaufler @ 2019-06-26 19:22 UTC (permalink / raw)
To: casey.schaufler, jmorris, linux-security-module, selinux
Cc: casey, keescook, john.johansen, penguin-kernel, paul, sds
In-Reply-To: <20190626192234.11725-1-casey@schaufler-ca.com>
Change the security_inode_getsecid() interface to fill in a
lsmblob structure instead of a u32 secid. This allows for its
callers to gather data from all registered LSMs. Data is provided
for IMA and audit.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
include/linux/security.h | 7 ++++---
kernel/auditsc.c | 6 +++++-
security/integrity/ima/ima_policy.c | 4 +---
security/security.c | 11 +++++++++--
4 files changed, 19 insertions(+), 9 deletions(-)
diff --git a/include/linux/security.h b/include/linux/security.h
index cfd7cf4b0be9..2d81cac418e3 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -362,7 +362,7 @@ int security_inode_killpriv(struct dentry *dentry);
int security_inode_getsecurity(struct inode *inode, const char *name, void **buffer, bool alloc);
int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags);
int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size);
-void security_inode_getsecid(struct inode *inode, u32 *secid);
+void security_inode_getsecid(struct inode *inode, struct lsmblob *blob);
int security_inode_copy_up(struct dentry *src, struct cred **new);
int security_inode_copy_up_xattr(const char *name);
int security_file_permission(struct file *file, int mask);
@@ -858,9 +858,10 @@ static inline int security_inode_listsecurity(struct inode *inode, char *buffer,
return 0;
}
-static inline void security_inode_getsecid(struct inode *inode, u32 *secid)
+static inline void security_inode_getsecid(struct inode *inode,
+ struct lsmblob *blob)
{
- *secid = 0;
+ lsmblob_init(blob, 0);
}
static inline int security_inode_copy_up(struct dentry *src, struct cred **new)
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 7112fe31684d..54797c0fc3b7 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -1910,13 +1910,17 @@ static inline int audit_copy_fcaps(struct audit_names *name,
void audit_copy_inode(struct audit_names *name, const struct dentry *dentry,
struct inode *inode, unsigned int flags)
{
+ struct lsmblob blob;
+
name->ino = inode->i_ino;
name->dev = inode->i_sb->s_dev;
name->mode = inode->i_mode;
name->uid = inode->i_uid;
name->gid = inode->i_gid;
name->rdev = inode->i_rdev;
- security_inode_getsecid(inode, &name->osid);
+ security_inode_getsecid(inode, &blob);
+ /* scaffolding until osid is updated */
+ name->osid = blob.secid[0];
if (flags & AUDIT_INODE_NOEVAL) {
name->fcap_ver = -1;
return;
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index e7b8ce942950..92ee3d984c73 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -326,7 +326,6 @@ static bool ima_match_rules(struct ima_rule_entry *rule, struct inode *inode,
return false;
for (i = 0; i < MAX_LSM_RULES; i++) {
int rc = 0;
- u32 osid;
struct lsmblob blob;
int retried = 0;
@@ -337,8 +336,7 @@ static bool ima_match_rules(struct ima_rule_entry *rule, struct inode *inode,
case LSM_OBJ_USER:
case LSM_OBJ_ROLE:
case LSM_OBJ_TYPE:
- security_inode_getsecid(inode, &osid);
- lsmblob_init(&blob, osid);
+ security_inode_getsecid(inode, &blob);
rc = security_filter_rule_match(&blob,
rule->lsm[i].type,
Audit_equal,
diff --git a/security/security.c b/security/security.c
index 2f123003b0b3..91388553d3d7 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1404,9 +1404,16 @@ int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer
}
EXPORT_SYMBOL(security_inode_listsecurity);
-void security_inode_getsecid(struct inode *inode, u32 *secid)
+void security_inode_getsecid(struct inode *inode, struct lsmblob *blob)
{
- call_void_hook(inode_getsecid, inode, secid);
+ struct security_hook_list *hp;
+
+ lsmblob_init(blob, 0);
+ hlist_for_each_entry(hp, &security_hook_heads.inode_getsecid, list) {
+ if (WARN_ON(hp->lsmid->slot < 0 || hp->lsmid->slot >= lsm_slot))
+ continue;
+ hp->hook.inode_getsecid(inode, &blob->secid[hp->lsmid->slot]);
+ }
}
int security_inode_copy_up(struct dentry *src, struct cred **new)
--
2.20.1
^ permalink raw reply related
* [PATCH v4 10/23] LSM: Use lsmblob in security_ipc_getsecid
From: Casey Schaufler @ 2019-06-26 19:22 UTC (permalink / raw)
To: casey.schaufler, jmorris, linux-security-module, selinux
Cc: casey, keescook, john.johansen, penguin-kernel, paul, sds
In-Reply-To: <20190626192234.11725-1-casey@schaufler-ca.com>
There may be more than one LSM that provides IPC data
for auditing. Change security_ipc_getsecid() to fill in
a lsmblob structure instead of the u32 secid. The
audit data structure containing the secid will be updated
later, so there is a bit of scaffolding here.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
include/linux/security.h | 7 ++++---
kernel/auditsc.c | 5 ++++-
security/security.c | 12 +++++++++---
3 files changed, 17 insertions(+), 7 deletions(-)
diff --git a/include/linux/security.h b/include/linux/security.h
index 7b4667cc4930..41dc3053094e 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -417,7 +417,7 @@ int security_task_prctl(int option, unsigned long arg2, unsigned long arg3,
unsigned long arg4, unsigned long arg5);
void security_task_to_inode(struct task_struct *p, struct inode *inode);
int security_ipc_permission(struct kern_ipc_perm *ipcp, short flag);
-void security_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid);
+void security_ipc_getsecid(struct kern_ipc_perm *ipcp, struct lsmblob *blob);
int security_msg_msg_alloc(struct msg_msg *msg);
void security_msg_msg_free(struct msg_msg *msg);
int security_msg_queue_alloc(struct kern_ipc_perm *msq);
@@ -1102,9 +1102,10 @@ static inline int security_ipc_permission(struct kern_ipc_perm *ipcp,
return 0;
}
-static inline void security_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
+static inline void security_ipc_getsecid(struct kern_ipc_perm *ipcp,
+ struct lsmblob *blob)
{
- *secid = 0;
+ lsmblob_init(blob, 0);
}
static inline int security_msg_msg_alloc(struct msg_msg *msg)
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index d31914088a82..148733ec3c72 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -2268,11 +2268,14 @@ void __audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat)
void __audit_ipc_obj(struct kern_ipc_perm *ipcp)
{
struct audit_context *context = audit_context();
+ struct lsmblob blob;
context->ipc.uid = ipcp->uid;
context->ipc.gid = ipcp->gid;
context->ipc.mode = ipcp->mode;
context->ipc.has_perm = 0;
- security_ipc_getsecid(ipcp, &context->ipc.osid);
+ security_ipc_getsecid(ipcp, &blob);
+ /* scaffolding on the [0] - change "osid" to a lsmblob */
+ context->ipc.osid = blob.secid[0];
context->type = AUDIT_IPC;
}
diff --git a/security/security.c b/security/security.c
index 0c7784a243e7..5245d4d1e799 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1795,10 +1795,16 @@ int security_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
return call_int_hook(ipc_permission, 0, ipcp, flag);
}
-void security_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
+void security_ipc_getsecid(struct kern_ipc_perm *ipcp, struct lsmblob *blob)
{
- *secid = 0;
- call_void_hook(ipc_getsecid, ipcp, secid);
+ struct security_hook_list *hp;
+
+ lsmblob_init(blob, 0);
+ hlist_for_each_entry(hp, &security_hook_heads.ipc_getsecid, list) {
+ if (WARN_ON(hp->lsmid->slot < 0 || hp->lsmid->slot >= lsm_slot))
+ continue;
+ hp->hook.ipc_getsecid(ipcp, &blob->secid[hp->lsmid->slot]);
+ }
}
int security_msg_msg_alloc(struct msg_msg *msg)
--
2.20.1
^ permalink raw reply related
* [PATCH v4 09/23] LSM: Use lsmblob in security_secid_to_secctx
From: Casey Schaufler @ 2019-06-26 19:22 UTC (permalink / raw)
To: casey.schaufler, jmorris, linux-security-module, selinux
Cc: casey, keescook, john.johansen, penguin-kernel, paul, sds
In-Reply-To: <20190626192234.11725-1-casey@schaufler-ca.com>
Change security_secid_to_secctx() to take a lsmblob as input
instead of a u32 secid. It will then call the LSM hooks
using the lsmblob element allocated for that module. The
callers have been updated as well. This allows for the
possibility that more than one module may be called upon
to translate a secid to a string, as can occur in the
audit code.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
drivers/android/binder.c | 4 +++-
include/linux/security.h | 5 +++--
include/net/scm.h | 5 ++---
kernel/audit.c | 9 +++++++--
kernel/auditsc.c | 14 ++++++++++----
net/ipv4/ip_sockglue.c | 3 +--
net/netfilter/nf_conntrack_netlink.c | 8 ++++++--
net/netfilter/nf_conntrack_standalone.c | 4 +++-
net/netfilter/nfnetlink_queue.c | 8 ++++++--
net/netlabel/netlabel_unlabeled.c | 18 ++++++++++++++----
net/netlabel/netlabel_user.c | 6 +++---
security/security.c | 16 +++++++++++++---
12 files changed, 71 insertions(+), 29 deletions(-)
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 8685882da64c..1962f6b8abd0 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -3120,9 +3120,11 @@ static void binder_transaction(struct binder_proc *proc,
if (target_node && target_node->txn_security_ctx) {
u32 secid;
+ struct lsmblob blob;
security_task_getsecid(proc->tsk, &secid);
- ret = security_secid_to_secctx(secid, &secctx, &secctx_sz);
+ lsmblob_init(&blob, secid);
+ ret = security_secid_to_secctx(&blob, &secctx, &secctx_sz);
if (ret) {
return_error = BR_FAILED_REPLY;
return_error_param = ret;
diff --git a/include/linux/security.h b/include/linux/security.h
index 30337f1a9056..7b4667cc4930 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -446,7 +446,7 @@ int security_setprocattr(const char *lsm, const char *name, void *value,
size_t size);
int security_netlink_send(struct sock *sk, struct sk_buff *skb);
int security_ismaclabel(const char *name);
-int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen);
+int security_secid_to_secctx(struct lsmblob *blob, char **secdata, u32 *seclen);
int security_secctx_to_secid(const char *secdata, u32 seclen,
struct lsmblob *blob);
void security_release_secctx(char *secdata, u32 seclen);
@@ -1224,7 +1224,8 @@ static inline int security_ismaclabel(const char *name)
return 0;
}
-static inline int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
+static inline int security_secid_to_secctx(struct lsmblob *blob,
+ char **secdata, u32 *seclen)
{
return -EOPNOTSUPP;
}
diff --git a/include/net/scm.h b/include/net/scm.h
index e2e71c4bf9d0..31ae605fcc0a 100644
--- a/include/net/scm.h
+++ b/include/net/scm.h
@@ -97,9 +97,8 @@ static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct sc
int err;
if (test_bit(SOCK_PASSSEC, &sock->flags)) {
- /* Scaffolding - it has to be element 0 for now */
- err = security_secid_to_secctx(scm->lsmblob.secid[0],
- &secdata, &seclen);
+ err = security_secid_to_secctx(&scm->lsmblob, &secdata,
+ &seclen);
if (!err) {
put_cmsg(msg, SOL_SOCKET, SCM_SECURITY, seclen, secdata);
diff --git a/kernel/audit.c b/kernel/audit.c
index c89ea48c70a6..d0338411d75d 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -1430,7 +1430,10 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
case AUDIT_SIGNAL_INFO:
len = 0;
if (audit_sig_sid) {
- err = security_secid_to_secctx(audit_sig_sid, &ctx, &len);
+ struct lsmblob blob;
+
+ lsmblob_init(&blob, audit_sig_sid);
+ err = security_secid_to_secctx(&blob, &ctx, &len);
if (err)
return err;
}
@@ -2073,12 +2076,14 @@ int audit_log_task_context(struct audit_buffer *ab)
unsigned len;
int error;
u32 sid;
+ struct lsmblob blob;
security_task_getsecid(current, &sid);
if (!sid)
return 0;
- error = security_secid_to_secctx(sid, &ctx, &len);
+ lsmblob_init(&blob, sid);
+ error = security_secid_to_secctx(&blob, &ctx, &len);
if (error) {
if (error != -EINVAL)
goto error_path;
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 18ee5556c086..d31914088a82 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -947,6 +947,7 @@ static int audit_log_pid_context(struct audit_context *context, pid_t pid,
char *ctx = NULL;
u32 len;
int rc = 0;
+ struct lsmblob blob;
ab = audit_log_start(context, GFP_KERNEL, AUDIT_OBJ_PID);
if (!ab)
@@ -956,7 +957,8 @@ static int audit_log_pid_context(struct audit_context *context, pid_t pid,
from_kuid(&init_user_ns, auid),
from_kuid(&init_user_ns, uid), sessionid);
if (sid) {
- if (security_secid_to_secctx(sid, &ctx, &len)) {
+ lsmblob_init(&blob, sid);
+ if (security_secid_to_secctx(&blob, &ctx, &len)) {
audit_log_format(ab, " obj=(none)");
rc = 1;
} else {
@@ -1198,7 +1200,10 @@ static void show_special(struct audit_context *context, int *call_panic)
if (osid) {
char *ctx = NULL;
u32 len;
- if (security_secid_to_secctx(osid, &ctx, &len)) {
+ struct lsmblob blob;
+
+ lsmblob_init(&blob, osid);
+ if (security_secid_to_secctx(&blob, &ctx, &len)) {
audit_log_format(ab, " osid=%u", osid);
*call_panic = 1;
} else {
@@ -1349,9 +1354,10 @@ static void audit_log_name(struct audit_context *context, struct audit_names *n,
if (n->osid != 0) {
char *ctx = NULL;
u32 len;
+ struct lsmblob blob;
- if (security_secid_to_secctx(
- n->osid, &ctx, &len)) {
+ lsmblob_init(&blob, n->osid);
+ if (security_secid_to_secctx(&blob, &ctx, &len)) {
audit_log_format(ab, " osid=%u", n->osid);
if (call_panic)
*call_panic = 2;
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index 2a5c868ce135..e05f4ef68bd8 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -139,8 +139,7 @@ static void ip_cmsg_recv_security(struct msghdr *msg, struct sk_buff *skb)
if (err)
return;
- /* Scaffolding - it has to be element 0 */
- err = security_secid_to_secctx(lb.secid[0], &secdata, &seclen);
+ err = security_secid_to_secctx(&lb, &secdata, &seclen);
if (err)
return;
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 66c596d287a5..ca0968f13240 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -330,8 +330,10 @@ static int ctnetlink_dump_secctx(struct sk_buff *skb, const struct nf_conn *ct)
struct nlattr *nest_secctx;
int len, ret;
char *secctx;
+ struct lsmblob blob;
- ret = security_secid_to_secctx(ct->secmark, &secctx, &len);
+ lsmblob_init(&blob, ct->secmark);
+ ret = security_secid_to_secctx(&blob, &secctx, &len);
if (ret)
return 0;
@@ -615,8 +617,10 @@ static inline int ctnetlink_secctx_size(const struct nf_conn *ct)
{
#ifdef CONFIG_NF_CONNTRACK_SECMARK
int len, ret;
+ struct lsmblob blob;
- ret = security_secid_to_secctx(ct->secmark, NULL, &len);
+ lsmblob_init(&blob, ct->secmark);
+ ret = security_secid_to_secctx(&blob, NULL, &len);
if (ret)
return 0;
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index c2ae14c720b4..c793103f3cd7 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -175,8 +175,10 @@ static void ct_show_secctx(struct seq_file *s, const struct nf_conn *ct)
int ret;
u32 len;
char *secctx;
+ struct lsmblob blob;
- ret = security_secid_to_secctx(ct->secmark, &secctx, &len);
+ lsmblob_init(&blob, ct->secmark);
+ ret = security_secid_to_secctx(&blob, &secctx, &len);
if (ret)
return;
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index 0dcc3592d053..59211bff90ab 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -309,13 +309,17 @@ static u32 nfqnl_get_sk_secctx(struct sk_buff *skb, char **secdata)
{
u32 seclen = 0;
#if IS_ENABLED(CONFIG_NETWORK_SECMARK)
+ struct lsmblob blob;
+
if (!skb || !sk_fullsock(skb->sk))
return 0;
read_lock_bh(&skb->sk->sk_callback_lock);
- if (skb->secmark)
- security_secid_to_secctx(skb->secmark, secdata, &seclen);
+ if (skb->secmark) {
+ lsmblob_init(&blob, skb->secmark);
+ security_secid_to_secctx(&blob, secdata, &seclen);
+ }
read_unlock_bh(&skb->sk->sk_callback_lock);
#endif
diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c
index 2976370e41aa..2d8dd5b84457 100644
--- a/net/netlabel/netlabel_unlabeled.c
+++ b/net/netlabel/netlabel_unlabeled.c
@@ -389,6 +389,7 @@ int netlbl_unlhsh_add(struct net *net,
struct audit_buffer *audit_buf = NULL;
char *secctx = NULL;
u32 secctx_len;
+ struct lsmblob blob;
if (addr_len != sizeof(struct in_addr) &&
addr_len != sizeof(struct in6_addr))
@@ -451,7 +452,8 @@ int netlbl_unlhsh_add(struct net *net,
unlhsh_add_return:
rcu_read_unlock();
if (audit_buf != NULL) {
- if (security_secid_to_secctx(secid,
+ lsmblob_init(&blob, secid);
+ if (security_secid_to_secctx(&blob,
&secctx,
&secctx_len) == 0) {
audit_log_format(audit_buf, " sec_obj=%s", secctx);
@@ -488,6 +490,7 @@ static int netlbl_unlhsh_remove_addr4(struct net *net,
struct net_device *dev;
char *secctx;
u32 secctx_len;
+ struct lsmblob blob;
spin_lock(&netlbl_unlhsh_lock);
list_entry = netlbl_af4list_remove(addr->s_addr, mask->s_addr,
@@ -507,8 +510,10 @@ static int netlbl_unlhsh_remove_addr4(struct net *net,
addr->s_addr, mask->s_addr);
if (dev != NULL)
dev_put(dev);
+ if (entry != NULL)
+ lsmblob_init(&blob, entry->secid);
if (entry != NULL &&
- security_secid_to_secctx(entry->secid,
+ security_secid_to_secctx(&blob,
&secctx, &secctx_len) == 0) {
audit_log_format(audit_buf, " sec_obj=%s", secctx);
security_release_secctx(secctx, secctx_len);
@@ -550,6 +555,7 @@ static int netlbl_unlhsh_remove_addr6(struct net *net,
struct net_device *dev;
char *secctx;
u32 secctx_len;
+ struct lsmblob blob;
spin_lock(&netlbl_unlhsh_lock);
list_entry = netlbl_af6list_remove(addr, mask, &iface->addr6_list);
@@ -568,8 +574,10 @@ static int netlbl_unlhsh_remove_addr6(struct net *net,
addr, mask);
if (dev != NULL)
dev_put(dev);
+ if (entry != NULL)
+ lsmblob_init(&blob, entry->secid);
if (entry != NULL &&
- security_secid_to_secctx(entry->secid,
+ security_secid_to_secctx(&blob,
&secctx, &secctx_len) == 0) {
audit_log_format(audit_buf, " sec_obj=%s", secctx);
security_release_secctx(secctx, secctx_len);
@@ -1090,6 +1098,7 @@ static int netlbl_unlabel_staticlist_gen(u32 cmd,
u32 secid;
char *secctx;
u32 secctx_len;
+ struct lsmblob blob;
data = genlmsg_put(cb_arg->skb, NETLINK_CB(cb_arg->nl_cb->skb).portid,
cb_arg->seq, &netlbl_unlabel_gnl_family,
@@ -1144,7 +1153,8 @@ static int netlbl_unlabel_staticlist_gen(u32 cmd,
secid = addr6->secid;
}
- ret_val = security_secid_to_secctx(secid, &secctx, &secctx_len);
+ lsmblob_init(&blob, secid);
+ ret_val = security_secid_to_secctx(&blob, &secctx, &secctx_len);
if (ret_val != 0)
goto list_cb_failure;
ret_val = nla_put(cb_arg->skb,
diff --git a/net/netlabel/netlabel_user.c b/net/netlabel/netlabel_user.c
index 4676f5bb16ae..2ccc6567e2a2 100644
--- a/net/netlabel/netlabel_user.c
+++ b/net/netlabel/netlabel_user.c
@@ -100,6 +100,7 @@ struct audit_buffer *netlbl_audit_start_common(int type,
struct audit_buffer *audit_buf;
char *secctx;
u32 secctx_len;
+ struct lsmblob blob;
if (audit_enabled == AUDIT_OFF)
return NULL;
@@ -112,10 +113,9 @@ struct audit_buffer *netlbl_audit_start_common(int type,
from_kuid(&init_user_ns, audit_info->loginuid),
audit_info->sessionid);
+ lsmblob_init(&blob, audit_info->secid);
if (audit_info->secid != 0 &&
- security_secid_to_secctx(audit_info->secid,
- &secctx,
- &secctx_len) == 0) {
+ security_secid_to_secctx(&blob, &secctx, &secctx_len) == 0) {
audit_log_format(audit_buf, " subj=%s", secctx);
security_release_secctx(secctx, secctx_len);
}
diff --git a/security/security.c b/security/security.c
index ad9aaa46ed04..0c7784a243e7 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1975,10 +1975,20 @@ int security_ismaclabel(const char *name)
}
EXPORT_SYMBOL(security_ismaclabel);
-int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
+int security_secid_to_secctx(struct lsmblob *blob, char **secdata, u32 *seclen)
{
- return call_int_hook(secid_to_secctx, -EOPNOTSUPP, secid, secdata,
- seclen);
+ struct security_hook_list *hp;
+ int rc;
+
+ hlist_for_each_entry(hp, &security_hook_heads.secid_to_secctx, list) {
+ if (WARN_ON(hp->lsmid->slot < 0 || hp->lsmid->slot >= lsm_slot))
+ continue;
+ rc = hp->hook.secid_to_secctx(blob->secid[hp->lsmid->slot],
+ secdata, seclen);
+ if (rc != 0)
+ return rc;
+ }
+ return 0;
}
EXPORT_SYMBOL(security_secid_to_secctx);
--
2.20.1
^ permalink raw reply related
* [PATCH v4 08/23] LSM: Use lsmblob in security_secctx_to_secid
From: Casey Schaufler @ 2019-06-26 19:22 UTC (permalink / raw)
To: casey.schaufler, jmorris, linux-security-module, selinux
Cc: casey, keescook, john.johansen, penguin-kernel, paul, sds
In-Reply-To: <20190626192234.11725-1-casey@schaufler-ca.com>
Change security_secctx_to_secid() to fill in a lsmblob instead
of a u32 secid. Multiple LSMs may be able to interpret the
string, and this allows for setting whichever secid is
appropriate. In some cases there is scaffolding where other
interfaces have yet to be converted.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
include/linux/security.h | 5 +++--
kernel/cred.c | 4 +---
net/netfilter/nft_meta.c | 13 ++++++-------
net/netfilter/xt_SECMARK.c | 5 ++++-
net/netlabel/netlabel_unlabeled.c | 14 ++++++++------
security/security.c | 18 +++++++++++++++---
6 files changed, 37 insertions(+), 22 deletions(-)
diff --git a/include/linux/security.h b/include/linux/security.h
index dcf20da87d1b..30337f1a9056 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -447,7 +447,8 @@ int security_setprocattr(const char *lsm, const char *name, void *value,
int security_netlink_send(struct sock *sk, struct sk_buff *skb);
int security_ismaclabel(const char *name);
int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen);
-int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid);
+int security_secctx_to_secid(const char *secdata, u32 seclen,
+ struct lsmblob *blob);
void security_release_secctx(char *secdata, u32 seclen);
void security_inode_invalidate_secctx(struct inode *inode);
@@ -1230,7 +1231,7 @@ static inline int security_secid_to_secctx(u32 secid, char **secdata, u32 *secle
static inline int security_secctx_to_secid(const char *secdata,
u32 seclen,
- u32 *secid)
+ struct lsmblob *blob)
{
return -EOPNOTSUPP;
}
diff --git a/kernel/cred.c b/kernel/cred.c
index 71c14dda107e..d70a2c02ced4 100644
--- a/kernel/cred.c
+++ b/kernel/cred.c
@@ -725,14 +725,12 @@ EXPORT_SYMBOL(set_security_override);
int set_security_override_from_ctx(struct cred *new, const char *secctx)
{
struct lsmblob blob;
- u32 secid;
int ret;
- ret = security_secctx_to_secid(secctx, strlen(secctx), &secid);
+ ret = security_secctx_to_secid(secctx, strlen(secctx), &blob);
if (ret < 0)
return ret;
- lsmblob_init(&blob, secid);
return set_security_override(new, &blob);
}
EXPORT_SYMBOL(set_security_override_from_ctx);
diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c
index 987d2d6ce624..054fb4b48d51 100644
--- a/net/netfilter/nft_meta.c
+++ b/net/netfilter/nft_meta.c
@@ -576,21 +576,20 @@ static const struct nla_policy nft_secmark_policy[NFTA_SECMARK_MAX + 1] = {
static int nft_secmark_compute_secid(struct nft_secmark *priv)
{
- u32 tmp_secid = 0;
+ struct lsmblob blob;
int err;
- err = security_secctx_to_secid(priv->ctx, strlen(priv->ctx), &tmp_secid);
+ err = security_secctx_to_secid(priv->ctx, strlen(priv->ctx), &blob);
if (err)
return err;
- if (!tmp_secid)
- return -ENOENT;
-
- err = security_secmark_relabel_packet(tmp_secid);
+ /* Using le[0] is scaffolding */
+ err = security_secmark_relabel_packet(blob.secid[0]);
if (err)
return err;
- priv->secid = tmp_secid;
+ /* Using le[0] is scaffolding */
+ priv->secid = blob.secid[0];
return 0;
}
diff --git a/net/netfilter/xt_SECMARK.c b/net/netfilter/xt_SECMARK.c
index f16202d26c20..8081fadc30e9 100644
--- a/net/netfilter/xt_SECMARK.c
+++ b/net/netfilter/xt_SECMARK.c
@@ -49,13 +49,14 @@ secmark_tg(struct sk_buff *skb, const struct xt_action_param *par)
static int checkentry_lsm(struct xt_secmark_target_info *info)
{
+ struct lsmblob blob;
int err;
info->secctx[SECMARK_SECCTX_MAX - 1] = '\0';
info->secid = 0;
err = security_secctx_to_secid(info->secctx, strlen(info->secctx),
- &info->secid);
+ &blob);
if (err) {
if (err == -EINVAL)
pr_info_ratelimited("invalid security context \'%s\'\n",
@@ -63,6 +64,8 @@ static int checkentry_lsm(struct xt_secmark_target_info *info)
return err;
}
+ /* scaffolding during the transition */
+ info->secid = blob.secid[0];
if (!info->secid) {
pr_info_ratelimited("unable to map security context \'%s\'\n",
info->secctx);
diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c
index c92894c3e40a..2976370e41aa 100644
--- a/net/netlabel/netlabel_unlabeled.c
+++ b/net/netlabel/netlabel_unlabeled.c
@@ -895,7 +895,7 @@ static int netlbl_unlabel_staticadd(struct sk_buff *skb,
void *addr;
void *mask;
u32 addr_len;
- u32 secid;
+ struct lsmblob blob;
struct netlbl_audit audit_info;
/* Don't allow users to add both IPv4 and IPv6 addresses for a
@@ -919,12 +919,13 @@ static int netlbl_unlabel_staticadd(struct sk_buff *skb,
ret_val = security_secctx_to_secid(
nla_data(info->attrs[NLBL_UNLABEL_A_SECCTX]),
nla_len(info->attrs[NLBL_UNLABEL_A_SECCTX]),
- &secid);
+ &blob);
if (ret_val != 0)
return ret_val;
+ /* scaffolding with the [0] */
return netlbl_unlhsh_add(&init_net,
- dev_name, addr, mask, addr_len, secid,
+ dev_name, addr, mask, addr_len, blob.secid[0],
&audit_info);
}
@@ -946,7 +947,7 @@ static int netlbl_unlabel_staticadddef(struct sk_buff *skb,
void *addr;
void *mask;
u32 addr_len;
- u32 secid;
+ struct lsmblob blob;
struct netlbl_audit audit_info;
/* Don't allow users to add both IPv4 and IPv6 addresses for a
@@ -968,12 +969,13 @@ static int netlbl_unlabel_staticadddef(struct sk_buff *skb,
ret_val = security_secctx_to_secid(
nla_data(info->attrs[NLBL_UNLABEL_A_SECCTX]),
nla_len(info->attrs[NLBL_UNLABEL_A_SECCTX]),
- &secid);
+ &blob);
if (ret_val != 0)
return ret_val;
+ /* scaffolding with the [0] */
return netlbl_unlhsh_add(&init_net,
- NULL, addr, mask, addr_len, secid,
+ NULL, addr, mask, addr_len, blob.secid[0],
&audit_info);
}
diff --git a/security/security.c b/security/security.c
index 4e1eb2a54064..ad9aaa46ed04 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1982,10 +1982,22 @@ int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
}
EXPORT_SYMBOL(security_secid_to_secctx);
-int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
+int security_secctx_to_secid(const char *secdata, u32 seclen,
+ struct lsmblob *blob)
{
- *secid = 0;
- return call_int_hook(secctx_to_secid, 0, secdata, seclen, secid);
+ struct security_hook_list *hp;
+ int rc;
+
+ lsmblob_init(blob, 0);
+ hlist_for_each_entry(hp, &security_hook_heads.secctx_to_secid, list) {
+ if (WARN_ON(hp->lsmid->slot < 0 || hp->lsmid->slot >= lsm_slot))
+ continue;
+ rc = hp->hook.secctx_to_secid(secdata, seclen,
+ &blob->secid[hp->lsmid->slot]);
+ if (rc != 0)
+ return rc;
+ }
+ return 0;
}
EXPORT_SYMBOL(security_secctx_to_secid);
--
2.20.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox