LCOV - code coverage report
Current view: top level - security/keys - user_defined.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 18 63 28.6 %
Date: 2022-03-28 15:32:58 Functions: 3 9 33.3 %
Branches: 4 32 12.5 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0-or-later
       2                 :            : /* user_defined.c: user defined key type
       3                 :            :  *
       4                 :            :  * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
       5                 :            :  * Written by David Howells (dhowells@redhat.com)
       6                 :            :  */
       7                 :            : 
       8                 :            : #include <linux/export.h>
       9                 :            : #include <linux/init.h>
      10                 :            : #include <linux/slab.h>
      11                 :            : #include <linux/seq_file.h>
      12                 :            : #include <linux/err.h>
      13                 :            : #include <keys/user-type.h>
      14                 :            : #include <linux/uaccess.h>
      15                 :            : #include "internal.h"
      16                 :            : 
      17                 :            : static int logon_vet_description(const char *desc);
      18                 :            : 
      19                 :            : /*
      20                 :            :  * user defined keys take an arbitrary string as the description and an
      21                 :            :  * arbitrary blob of data as the payload
      22                 :            :  */
      23                 :            : struct key_type key_type_user = {
      24                 :            :         .name                   = "user",
      25                 :            :         .preparse               = user_preparse,
      26                 :            :         .free_preparse          = user_free_preparse,
      27                 :            :         .instantiate            = generic_key_instantiate,
      28                 :            :         .update                 = user_update,
      29                 :            :         .revoke                 = user_revoke,
      30                 :            :         .destroy                = user_destroy,
      31                 :            :         .describe               = user_describe,
      32                 :            :         .read                   = user_read,
      33                 :            : };
      34                 :            : 
      35                 :            : EXPORT_SYMBOL_GPL(key_type_user);
      36                 :            : 
      37                 :            : /*
      38                 :            :  * This key type is essentially the same as key_type_user, but it does
      39                 :            :  * not define a .read op. This is suitable for storing username and
      40                 :            :  * password pairs in the keyring that you do not want to be readable
      41                 :            :  * from userspace.
      42                 :            :  */
      43                 :            : struct key_type key_type_logon = {
      44                 :            :         .name                   = "logon",
      45                 :            :         .preparse               = user_preparse,
      46                 :            :         .free_preparse          = user_free_preparse,
      47                 :            :         .instantiate            = generic_key_instantiate,
      48                 :            :         .update                 = user_update,
      49                 :            :         .revoke                 = user_revoke,
      50                 :            :         .destroy                = user_destroy,
      51                 :            :         .describe               = user_describe,
      52                 :            :         .vet_description        = logon_vet_description,
      53                 :            : };
      54                 :            : EXPORT_SYMBOL_GPL(key_type_logon);
      55                 :            : 
      56                 :            : /*
      57                 :            :  * Preparse a user defined key payload
      58                 :            :  */
      59                 :        784 : int user_preparse(struct key_preparsed_payload *prep)
      60                 :            : {
      61                 :        784 :         struct user_key_payload *upayload;
      62                 :        784 :         size_t datalen = prep->datalen;
      63                 :            : 
      64   [ +  -  +  - ]:        784 :         if (datalen <= 0 || datalen > 32767 || !prep->data)
      65                 :            :                 return -EINVAL;
      66                 :            : 
      67         [ -  + ]:        784 :         upayload = kmalloc(sizeof(*upayload) + datalen, GFP_KERNEL);
      68         [ +  - ]:        784 :         if (!upayload)
      69                 :            :                 return -ENOMEM;
      70                 :            : 
      71                 :            :         /* attach the data */
      72                 :        784 :         prep->quotalen = datalen;
      73                 :        784 :         prep->payload.data[0] = upayload;
      74                 :        784 :         upayload->datalen = datalen;
      75                 :        784 :         memcpy(upayload->data, prep->data, datalen);
      76                 :        784 :         return 0;
      77                 :            : }
      78                 :            : EXPORT_SYMBOL_GPL(user_preparse);
      79                 :            : 
      80                 :            : /*
      81                 :            :  * Free a preparse of a user defined key payload
      82                 :            :  */
      83                 :        784 : void user_free_preparse(struct key_preparsed_payload *prep)
      84                 :            : {
      85                 :        784 :         kzfree(prep->payload.data[0]);
      86                 :        784 : }
      87                 :            : EXPORT_SYMBOL_GPL(user_free_preparse);
      88                 :            : 
      89                 :          0 : static void user_free_payload_rcu(struct rcu_head *head)
      90                 :            : {
      91                 :          0 :         struct user_key_payload *payload;
      92                 :            : 
      93                 :          0 :         payload = container_of(head, struct user_key_payload, rcu);
      94                 :          0 :         kzfree(payload);
      95                 :          0 : }
      96                 :            : 
      97                 :            : /*
      98                 :            :  * update a user defined key
      99                 :            :  * - the key's semaphore is write-locked
     100                 :            :  */
     101                 :          0 : int user_update(struct key *key, struct key_preparsed_payload *prep)
     102                 :            : {
     103                 :          0 :         struct user_key_payload *zap = NULL;
     104                 :          0 :         int ret;
     105                 :            : 
     106                 :            :         /* check the quota and attach the new data */
     107                 :          0 :         ret = key_payload_reserve(key, prep->datalen);
     108         [ #  # ]:          0 :         if (ret < 0)
     109                 :            :                 return ret;
     110                 :            : 
     111                 :            :         /* attach the new data, displacing the old */
     112                 :          0 :         key->expiry = prep->expiry;
     113         [ #  # ]:          0 :         if (key_is_positive(key))
     114                 :          0 :                 zap = dereference_key_locked(key);
     115         [ #  # ]:          0 :         rcu_assign_keypointer(key, prep->payload.data[0]);
     116                 :          0 :         prep->payload.data[0] = NULL;
     117                 :            : 
     118         [ #  # ]:          0 :         if (zap)
     119                 :          0 :                 call_rcu(&zap->rcu, user_free_payload_rcu);
     120                 :            :         return ret;
     121                 :            : }
     122                 :            : EXPORT_SYMBOL_GPL(user_update);
     123                 :            : 
     124                 :            : /*
     125                 :            :  * dispose of the links from a revoked keyring
     126                 :            :  * - called with the key sem write-locked
     127                 :            :  */
     128                 :          0 : void user_revoke(struct key *key)
     129                 :            : {
     130                 :          0 :         struct user_key_payload *upayload = user_key_payload_locked(key);
     131                 :            : 
     132                 :            :         /* clear the quota */
     133                 :          0 :         key_payload_reserve(key, 0);
     134                 :            : 
     135         [ #  # ]:          0 :         if (upayload) {
     136                 :          0 :                 rcu_assign_keypointer(key, NULL);
     137                 :          0 :                 call_rcu(&upayload->rcu, user_free_payload_rcu);
     138                 :            :         }
     139                 :          0 : }
     140                 :            : 
     141                 :            : EXPORT_SYMBOL(user_revoke);
     142                 :            : 
     143                 :            : /*
     144                 :            :  * dispose of the data dangling from the corpse of a user key
     145                 :            :  */
     146                 :        588 : void user_destroy(struct key *key)
     147                 :            : {
     148                 :        588 :         struct user_key_payload *upayload = key->payload.data[0];
     149                 :            : 
     150                 :        588 :         kzfree(upayload);
     151                 :        588 : }
     152                 :            : 
     153                 :            : EXPORT_SYMBOL_GPL(user_destroy);
     154                 :            : 
     155                 :            : /*
     156                 :            :  * describe the user key
     157                 :            :  */
     158                 :          0 : void user_describe(const struct key *key, struct seq_file *m)
     159                 :            : {
     160                 :          0 :         seq_puts(m, key->description);
     161         [ #  # ]:          0 :         if (key_is_positive(key))
     162                 :          0 :                 seq_printf(m, ": %u", key->datalen);
     163                 :          0 : }
     164                 :            : 
     165                 :            : EXPORT_SYMBOL_GPL(user_describe);
     166                 :            : 
     167                 :            : /*
     168                 :            :  * read the key data
     169                 :            :  * - the key's semaphore is read-locked
     170                 :            :  */
     171                 :          0 : long user_read(const struct key *key, char __user *buffer, size_t buflen)
     172                 :            : {
     173                 :          0 :         const struct user_key_payload *upayload;
     174                 :          0 :         long ret;
     175                 :            : 
     176         [ #  # ]:          0 :         upayload = user_key_payload_locked(key);
     177                 :          0 :         ret = upayload->datalen;
     178                 :            : 
     179                 :            :         /* we can return the data as is */
     180         [ #  # ]:          0 :         if (buffer && buflen > 0) {
     181                 :          0 :                 if (buflen > upayload->datalen)
     182                 :            :                         buflen = upayload->datalen;
     183                 :            : 
     184   [ #  #  #  # ]:          0 :                 if (copy_to_user(buffer, upayload->data, buflen) != 0)
     185                 :          0 :                         ret = -EFAULT;
     186                 :            :         }
     187                 :            : 
     188                 :          0 :         return ret;
     189                 :            : }
     190                 :            : 
     191                 :            : EXPORT_SYMBOL_GPL(user_read);
     192                 :            : 
     193                 :            : /* Vet the description for a "logon" key */
     194                 :          0 : static int logon_vet_description(const char *desc)
     195                 :            : {
     196                 :          0 :         char *p;
     197                 :            : 
     198                 :            :         /* require a "qualified" description string */
     199                 :          0 :         p = strchr(desc, ':');
     200         [ #  # ]:          0 :         if (!p)
     201                 :            :                 return -EINVAL;
     202                 :            : 
     203                 :            :         /* also reject description with ':' as first char */
     204         [ #  # ]:          0 :         if (p == desc)
     205                 :          0 :                 return -EINVAL;
     206                 :            : 
     207                 :            :         return 0;
     208                 :            : }

Generated by: LCOV version 1.14