LCOV - code coverage report
Current view: top level - fs - binfmt_misc.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 33 406 8.1 %
Date: 2022-04-01 14:58:12 Functions: 6 19 31.6 %
Branches: 6 231 2.6 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0-only
       2                 :            : /*
       3                 :            :  * binfmt_misc.c
       4                 :            :  *
       5                 :            :  * Copyright (C) 1997 Richard Günther
       6                 :            :  *
       7                 :            :  * binfmt_misc detects binaries via a magic or filename extension and invokes
       8                 :            :  * a specified wrapper. See Documentation/admin-guide/binfmt-misc.rst for more details.
       9                 :            :  */
      10                 :            : 
      11                 :            : #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
      12                 :            : 
      13                 :            : #include <linux/kernel.h>
      14                 :            : #include <linux/module.h>
      15                 :            : #include <linux/init.h>
      16                 :            : #include <linux/sched/mm.h>
      17                 :            : #include <linux/magic.h>
      18                 :            : #include <linux/binfmts.h>
      19                 :            : #include <linux/slab.h>
      20                 :            : #include <linux/ctype.h>
      21                 :            : #include <linux/string_helpers.h>
      22                 :            : #include <linux/file.h>
      23                 :            : #include <linux/pagemap.h>
      24                 :            : #include <linux/namei.h>
      25                 :            : #include <linux/mount.h>
      26                 :            : #include <linux/fs_context.h>
      27                 :            : #include <linux/syscalls.h>
      28                 :            : #include <linux/fs.h>
      29                 :            : #include <linux/uaccess.h>
      30                 :            : 
      31                 :            : #include "internal.h"
      32                 :            : 
      33                 :            : #ifdef DEBUG
      34                 :            : # define USE_DEBUG 1
      35                 :            : #else
      36                 :            : # define USE_DEBUG 0
      37                 :            : #endif
      38                 :            : 
      39                 :            : enum {
      40                 :            :         VERBOSE_STATUS = 1 /* make it zero to save 400 bytes kernel memory */
      41                 :            : };
      42                 :            : 
      43                 :            : static LIST_HEAD(entries);
      44                 :            : static int enabled = 1;
      45                 :            : 
      46                 :            : enum {Enabled, Magic};
      47                 :            : #define MISC_FMT_PRESERVE_ARGV0 (1 << 31)
      48                 :            : #define MISC_FMT_OPEN_BINARY (1 << 30)
      49                 :            : #define MISC_FMT_CREDENTIALS (1 << 29)
      50                 :            : #define MISC_FMT_OPEN_FILE (1 << 28)
      51                 :            : 
      52                 :            : typedef struct {
      53                 :            :         struct list_head list;
      54                 :            :         unsigned long flags;            /* type, status, etc. */
      55                 :            :         int offset;                     /* offset of magic */
      56                 :            :         int size;                       /* size of magic/mask */
      57                 :            :         char *magic;                    /* magic or filename extension */
      58                 :            :         char *mask;                     /* mask, NULL for exact match */
      59                 :            :         const char *interpreter;        /* filename of interpreter */
      60                 :            :         char *name;
      61                 :            :         struct dentry *dentry;
      62                 :            :         struct file *interp_file;
      63                 :            : } Node;
      64                 :            : 
      65                 :            : static DEFINE_RWLOCK(entries_lock);
      66                 :            : static struct file_system_type bm_fs_type;
      67                 :            : static struct vfsmount *bm_mnt;
      68                 :            : static int entry_count;
      69                 :            : 
      70                 :            : /*
      71                 :            :  * Max length of the register string.  Determined by:
      72                 :            :  *  - 7 delimiters
      73                 :            :  *  - name:   ~50 bytes
      74                 :            :  *  - type:   1 byte
      75                 :            :  *  - offset: 3 bytes (has to be smaller than BINPRM_BUF_SIZE)
      76                 :            :  *  - magic:  128 bytes (512 in escaped form)
      77                 :            :  *  - mask:   128 bytes (512 in escaped form)
      78                 :            :  *  - interp: ~50 bytes
      79                 :            :  *  - flags:  5 bytes
      80                 :            :  * Round that up a bit, and then back off to hold the internal data
      81                 :            :  * (like struct Node).
      82                 :            :  */
      83                 :            : #define MAX_REGISTER_LENGTH 1920
      84                 :            : 
      85                 :            : /*
      86                 :            :  * Check if we support the binfmt
      87                 :            :  * if we do, return the node, else NULL
      88                 :            :  * locking is done in load_misc_binary
      89                 :            :  */
      90                 :       3063 : static Node *check_file(struct linux_binprm *bprm)
      91                 :            : {
      92                 :       3063 :         char *p = strrchr(bprm->interp, '.');
      93                 :       3063 :         struct list_head *l;
      94                 :            : 
      95                 :            :         /* Walk all the registered handlers. */
      96         [ -  + ]:       3063 :         list_for_each(l, &entries) {
      97                 :          0 :                 Node *e = list_entry(l, Node, list);
      98                 :          0 :                 char *s;
      99                 :          0 :                 int j;
     100                 :            : 
     101                 :            :                 /* Make sure this one is currently enabled. */
     102         [ #  # ]:          0 :                 if (!test_bit(Enabled, &e->flags))
     103                 :          0 :                         continue;
     104                 :            : 
     105                 :            :                 /* Do matching based on extension if applicable. */
     106         [ #  # ]:          0 :                 if (!test_bit(Magic, &e->flags)) {
     107   [ #  #  #  # ]:          0 :                         if (p && !strcmp(e->magic, p + 1))
     108                 :          0 :                                 return e;
     109                 :          0 :                         continue;
     110                 :            :                 }
     111                 :            : 
     112                 :            :                 /* Do matching based on magic & mask. */
     113                 :          0 :                 s = bprm->buf + e->offset;
     114         [ #  # ]:          0 :                 if (e->mask) {
     115         [ #  # ]:          0 :                         for (j = 0; j < e->size; j++)
     116         [ #  # ]:          0 :                                 if ((*s++ ^ e->magic[j]) & e->mask[j])
     117                 :            :                                         break;
     118                 :            :                 } else {
     119         [ #  # ]:          0 :                         for (j = 0; j < e->size; j++)
     120         [ #  # ]:          0 :                                 if ((*s++ ^ e->magic[j]))
     121                 :            :                                         break;
     122                 :            :                 }
     123         [ #  # ]:          0 :                 if (j == e->size)
     124                 :          0 :                         return e;
     125                 :            :         }
     126                 :            :         return NULL;
     127                 :            : }
     128                 :            : 
     129                 :            : /*
     130                 :            :  * the loader itself
     131                 :            :  */
     132                 :       3063 : static int load_misc_binary(struct linux_binprm *bprm)
     133                 :            : {
     134                 :       3063 :         Node *fmt;
     135                 :       3063 :         struct file *interp_file = NULL;
     136                 :       3063 :         int retval;
     137                 :       3063 :         int fd_binary = -1;
     138                 :            : 
     139                 :       3063 :         retval = -ENOEXEC;
     140         [ +  - ]:       3063 :         if (!enabled)
     141                 :            :                 return retval;
     142                 :            : 
     143                 :            :         /* to keep locking time low, we copy the interpreter string */
     144                 :       3063 :         read_lock(&entries_lock);
     145                 :       3063 :         fmt = check_file(bprm);
     146         [ -  + ]:       3063 :         if (fmt)
     147         [ #  # ]:          0 :                 dget(fmt->dentry);
     148                 :       3063 :         read_unlock(&entries_lock);
     149         [ -  + ]:       3063 :         if (!fmt)
     150                 :            :                 return retval;
     151                 :            : 
     152                 :            :         /* Need to be able to load the file after exec */
     153                 :          0 :         retval = -ENOENT;
     154         [ #  # ]:          0 :         if (bprm->interp_flags & BINPRM_FLAGS_PATH_INACCESSIBLE)
     155                 :          0 :                 goto ret;
     156                 :            : 
     157         [ #  # ]:          0 :         if (!(fmt->flags & MISC_FMT_PRESERVE_ARGV0)) {
     158                 :          0 :                 retval = remove_arg_zero(bprm);
     159         [ #  # ]:          0 :                 if (retval)
     160                 :          0 :                         goto ret;
     161                 :            :         }
     162                 :            : 
     163         [ #  # ]:          0 :         if (fmt->flags & MISC_FMT_OPEN_BINARY) {
     164                 :            : 
     165                 :            :                 /* if the binary should be opened on behalf of the
     166                 :            :                  * interpreter than keep it open and assign descriptor
     167                 :            :                  * to it
     168                 :            :                  */
     169                 :          0 :                 fd_binary = get_unused_fd_flags(0);
     170         [ #  # ]:          0 :                 if (fd_binary < 0) {
     171                 :          0 :                         retval = fd_binary;
     172                 :          0 :                         goto ret;
     173                 :            :                 }
     174                 :          0 :                 fd_install(fd_binary, bprm->file);
     175                 :            : 
     176                 :            :                 /* if the binary is not readable than enforce mm->dumpable=0
     177                 :            :                    regardless of the interpreter's permissions */
     178                 :          0 :                 would_dump(bprm, bprm->file);
     179                 :            : 
     180         [ #  # ]:          0 :                 allow_write_access(bprm->file);
     181                 :          0 :                 bprm->file = NULL;
     182                 :            : 
     183                 :            :                 /* mark the bprm that fd should be passed to interp */
     184                 :          0 :                 bprm->interp_flags |= BINPRM_FLAGS_EXECFD;
     185                 :          0 :                 bprm->interp_data = fd_binary;
     186                 :            : 
     187                 :            :         } else {
     188         [ #  # ]:          0 :                 allow_write_access(bprm->file);
     189                 :          0 :                 fput(bprm->file);
     190                 :          0 :                 bprm->file = NULL;
     191                 :            :         }
     192                 :            :         /* make argv[1] be the path to the binary */
     193                 :          0 :         retval = copy_strings_kernel(1, &bprm->interp, bprm);
     194         [ #  # ]:          0 :         if (retval < 0)
     195                 :          0 :                 goto error;
     196                 :          0 :         bprm->argc++;
     197                 :            : 
     198                 :            :         /* add the interp as argv[0] */
     199                 :          0 :         retval = copy_strings_kernel(1, &fmt->interpreter, bprm);
     200         [ #  # ]:          0 :         if (retval < 0)
     201                 :          0 :                 goto error;
     202                 :          0 :         bprm->argc++;
     203                 :            : 
     204                 :            :         /* Update interp in case binfmt_script needs it. */
     205                 :          0 :         retval = bprm_change_interp(fmt->interpreter, bprm);
     206         [ #  # ]:          0 :         if (retval < 0)
     207                 :          0 :                 goto error;
     208                 :            : 
     209         [ #  # ]:          0 :         if (fmt->flags & MISC_FMT_OPEN_FILE) {
     210                 :          0 :                 interp_file = file_clone_open(fmt->interp_file);
     211         [ #  # ]:          0 :                 if (!IS_ERR(interp_file))
     212                 :          0 :                         deny_write_access(interp_file);
     213                 :            :         } else {
     214                 :          0 :                 interp_file = open_exec(fmt->interpreter);
     215                 :            :         }
     216         [ #  # ]:          0 :         retval = PTR_ERR(interp_file);
     217         [ #  # ]:          0 :         if (IS_ERR(interp_file))
     218                 :          0 :                 goto error;
     219                 :            : 
     220                 :          0 :         bprm->file = interp_file;
     221         [ #  # ]:          0 :         if (fmt->flags & MISC_FMT_CREDENTIALS) {
     222                 :          0 :                 loff_t pos = 0;
     223                 :            : 
     224                 :            :                 /*
     225                 :            :                  * No need to call prepare_binprm(), it's already been
     226                 :            :                  * done.  bprm->buf is stale, update from interp_file.
     227                 :            :                  */
     228                 :          0 :                 memset(bprm->buf, 0, BINPRM_BUF_SIZE);
     229                 :          0 :                 retval = kernel_read(bprm->file, bprm->buf, BINPRM_BUF_SIZE,
     230                 :            :                                 &pos);
     231                 :            :         } else
     232                 :          0 :                 retval = prepare_binprm(bprm);
     233                 :            : 
     234         [ #  # ]:          0 :         if (retval < 0)
     235                 :          0 :                 goto error;
     236                 :            : 
     237                 :          0 :         retval = search_binary_handler(bprm);
     238         [ #  # ]:          0 :         if (retval < 0)
     239                 :          0 :                 goto error;
     240                 :            : 
     241                 :          0 : ret:
     242                 :          0 :         dput(fmt->dentry);
     243                 :          0 :         return retval;
     244                 :          0 : error:
     245         [ #  # ]:          0 :         if (fd_binary > 0)
     246                 :          0 :                 ksys_close(fd_binary);
     247                 :          0 :         bprm->interp_flags = 0;
     248                 :          0 :         bprm->interp_data = 0;
     249                 :          0 :         goto ret;
     250                 :            : }
     251                 :            : 
     252                 :            : /* Command parsers */
     253                 :            : 
     254                 :            : /*
     255                 :            :  * parses and copies one argument enclosed in del from *sp to *dp,
     256                 :            :  * recognising the \x special.
     257                 :            :  * returns pointer to the copied argument or NULL in case of an
     258                 :            :  * error (and sets err) or null argument length.
     259                 :            :  */
     260                 :          0 : static char *scanarg(char *s, char del)
     261                 :            : {
     262                 :          0 :         char c;
     263                 :            : 
     264         [ #  # ]:          0 :         while ((c = *s++) != del) {
     265   [ #  #  #  # ]:          0 :                 if (c == '\\' && *s == 'x') {
     266                 :          0 :                         s++;
     267         [ #  # ]:          0 :                         if (!isxdigit(*s++))
     268                 :            :                                 return NULL;
     269         [ #  # ]:          0 :                         if (!isxdigit(*s++))
     270                 :            :                                 return NULL;
     271                 :            :                 }
     272                 :            :         }
     273                 :          0 :         s[-1] ='\0';
     274                 :          0 :         return s;
     275                 :            : }
     276                 :            : 
     277                 :            : static char *check_special_flags(char *sfs, Node *e)
     278                 :            : {
     279                 :            :         char *p = sfs;
     280                 :            :         int cont = 1;
     281                 :            : 
     282                 :            :         /* special flags */
     283                 :            :         while (cont) {
     284                 :            :                 switch (*p) {
     285                 :            :                 case 'P':
     286                 :            :                         pr_debug("register: flag: P (preserve argv0)\n");
     287                 :            :                         p++;
     288                 :            :                         e->flags |= MISC_FMT_PRESERVE_ARGV0;
     289                 :            :                         break;
     290                 :            :                 case 'O':
     291                 :            :                         pr_debug("register: flag: O (open binary)\n");
     292                 :            :                         p++;
     293                 :            :                         e->flags |= MISC_FMT_OPEN_BINARY;
     294                 :            :                         break;
     295                 :            :                 case 'C':
     296                 :            :                         pr_debug("register: flag: C (preserve creds)\n");
     297                 :            :                         p++;
     298                 :            :                         /* this flags also implies the
     299                 :            :                            open-binary flag */
     300                 :            :                         e->flags |= (MISC_FMT_CREDENTIALS |
     301                 :            :                                         MISC_FMT_OPEN_BINARY);
     302                 :            :                         break;
     303                 :            :                 case 'F':
     304                 :            :                         pr_debug("register: flag: F: open interpreter file now\n");
     305                 :            :                         p++;
     306                 :            :                         e->flags |= MISC_FMT_OPEN_FILE;
     307                 :            :                         break;
     308                 :            :                 default:
     309                 :            :                         cont = 0;
     310                 :            :                 }
     311                 :            :         }
     312                 :            : 
     313                 :            :         return p;
     314                 :            : }
     315                 :            : 
     316                 :            : /*
     317                 :            :  * This registers a new binary format, it recognises the syntax
     318                 :            :  * ':name:type:offset:magic:mask:interpreter:flags'
     319                 :            :  * where the ':' is the IFS, that can be chosen with the first char
     320                 :            :  */
     321                 :          0 : static Node *create_entry(const char __user *buffer, size_t count)
     322                 :            : {
     323                 :          0 :         Node *e;
     324                 :          0 :         int memsize, err;
     325                 :          0 :         char *buf, *p;
     326                 :          0 :         char del;
     327                 :            : 
     328                 :          0 :         pr_debug("register: received %zu bytes\n", count);
     329                 :            : 
     330                 :            :         /* some sanity checks */
     331                 :          0 :         err = -EINVAL;
     332         [ #  # ]:          0 :         if ((count < 11) || (count > MAX_REGISTER_LENGTH))
     333                 :          0 :                 goto out;
     334                 :            : 
     335                 :          0 :         err = -ENOMEM;
     336                 :          0 :         memsize = sizeof(Node) + count + 8;
     337         [ #  # ]:          0 :         e = kmalloc(memsize, GFP_KERNEL);
     338         [ #  # ]:          0 :         if (!e)
     339                 :          0 :                 goto out;
     340                 :            : 
     341                 :          0 :         p = buf = (char *)e + sizeof(Node);
     342                 :            : 
     343                 :          0 :         memset(e, 0, sizeof(Node));
     344   [ #  #  #  # ]:          0 :         if (copy_from_user(buf, buffer, count))
     345                 :          0 :                 goto efault;
     346                 :            : 
     347                 :          0 :         del = *p++;     /* delimeter */
     348                 :            : 
     349                 :          0 :         pr_debug("register: delim: %#x {%c}\n", del, del);
     350                 :            : 
     351                 :            :         /* Pad the buffer with the delim to simplify parsing below. */
     352                 :          0 :         memset(buf + count, del, 8);
     353                 :            : 
     354                 :            :         /* Parse the 'name' field. */
     355                 :          0 :         e->name = p;
     356                 :          0 :         p = strchr(p, del);
     357         [ #  # ]:          0 :         if (!p)
     358                 :          0 :                 goto einval;
     359                 :          0 :         *p++ = '\0';
     360         [ #  # ]:          0 :         if (!e->name[0] ||
     361         [ #  # ]:          0 :             !strcmp(e->name, ".") ||
     362         [ #  # ]:          0 :             !strcmp(e->name, "..") ||
     363         [ #  # ]:          0 :             strchr(e->name, '/'))
     364                 :          0 :                 goto einval;
     365                 :            : 
     366                 :          0 :         pr_debug("register: name: {%s}\n", e->name);
     367                 :            : 
     368                 :            :         /* Parse the 'type' field. */
     369      [ #  #  # ]:          0 :         switch (*p++) {
     370                 :            :         case 'E':
     371                 :          0 :                 pr_debug("register: type: E (extension)\n");
     372                 :          0 :                 e->flags = 1 << Enabled;
     373                 :          0 :                 break;
     374                 :            :         case 'M':
     375                 :          0 :                 pr_debug("register: type: M (magic)\n");
     376                 :          0 :                 e->flags = (1 << Enabled) | (1 << Magic);
     377                 :          0 :                 break;
     378                 :          0 :         default:
     379                 :          0 :                 goto einval;
     380                 :            :         }
     381         [ #  # ]:          0 :         if (*p++ != del)
     382                 :          0 :                 goto einval;
     383                 :            : 
     384         [ #  # ]:          0 :         if (test_bit(Magic, &e->flags)) {
     385                 :            :                 /* Handle the 'M' (magic) format. */
     386                 :          0 :                 char *s;
     387                 :            : 
     388                 :            :                 /* Parse the 'offset' field. */
     389                 :          0 :                 s = strchr(p, del);
     390         [ #  # ]:          0 :                 if (!s)
     391                 :          0 :                         goto einval;
     392                 :          0 :                 *s = '\0';
     393         [ #  # ]:          0 :                 if (p != s) {
     394                 :          0 :                         int r = kstrtoint(p, 10, &e->offset);
     395   [ #  #  #  # ]:          0 :                         if (r != 0 || e->offset < 0)
     396                 :          0 :                                 goto einval;
     397                 :            :                 }
     398                 :          0 :                 p = s;
     399         [ #  # ]:          0 :                 if (*p++)
     400                 :          0 :                         goto einval;
     401                 :          0 :                 pr_debug("register: offset: %#x\n", e->offset);
     402                 :            : 
     403                 :            :                 /* Parse the 'magic' field. */
     404                 :          0 :                 e->magic = p;
     405                 :          0 :                 p = scanarg(p, del);
     406         [ #  # ]:          0 :                 if (!p)
     407                 :          0 :                         goto einval;
     408         [ #  # ]:          0 :                 if (!e->magic[0])
     409                 :          0 :                         goto einval;
     410                 :          0 :                 if (USE_DEBUG)
     411                 :            :                         print_hex_dump_bytes(
     412                 :            :                                 KBUILD_MODNAME ": register: magic[raw]: ",
     413                 :            :                                 DUMP_PREFIX_NONE, e->magic, p - e->magic);
     414                 :            : 
     415                 :            :                 /* Parse the 'mask' field. */
     416                 :          0 :                 e->mask = p;
     417                 :          0 :                 p = scanarg(p, del);
     418         [ #  # ]:          0 :                 if (!p)
     419                 :          0 :                         goto einval;
     420         [ #  # ]:          0 :                 if (!e->mask[0]) {
     421                 :          0 :                         e->mask = NULL;
     422                 :          0 :                         pr_debug("register:  mask[raw]: none\n");
     423                 :            :                 } else if (USE_DEBUG)
     424                 :            :                         print_hex_dump_bytes(
     425                 :            :                                 KBUILD_MODNAME ": register:  mask[raw]: ",
     426                 :            :                                 DUMP_PREFIX_NONE, e->mask, p - e->mask);
     427                 :            : 
     428                 :            :                 /*
     429                 :            :                  * Decode the magic & mask fields.
     430                 :            :                  * Note: while we might have accepted embedded NUL bytes from
     431                 :            :                  * above, the unescape helpers here will stop at the first one
     432                 :            :                  * it encounters.
     433                 :            :                  */
     434                 :          0 :                 e->size = string_unescape_inplace(e->magic, UNESCAPE_HEX);
     435         [ #  # ]:          0 :                 if (e->mask &&
     436         [ #  # ]:          0 :                     string_unescape_inplace(e->mask, UNESCAPE_HEX) != e->size)
     437                 :          0 :                         goto einval;
     438         [ #  # ]:          0 :                 if (e->size > BINPRM_BUF_SIZE ||
     439         [ #  # ]:          0 :                     BINPRM_BUF_SIZE - e->size < e->offset)
     440                 :          0 :                         goto einval;
     441                 :            :                 pr_debug("register: magic/mask length: %i\n", e->size);
     442                 :            :                 if (USE_DEBUG) {
     443                 :            :                         print_hex_dump_bytes(
     444                 :            :                                 KBUILD_MODNAME ": register: magic[decoded]: ",
     445                 :            :                                 DUMP_PREFIX_NONE, e->magic, e->size);
     446                 :            : 
     447                 :            :                         if (e->mask) {
     448                 :            :                                 int i;
     449                 :            :                                 char *masked = kmalloc(e->size, GFP_KERNEL);
     450                 :            : 
     451                 :            :                                 print_hex_dump_bytes(
     452                 :            :                                         KBUILD_MODNAME ": register:  mask[decoded]: ",
     453                 :            :                                         DUMP_PREFIX_NONE, e->mask, e->size);
     454                 :            : 
     455                 :            :                                 if (masked) {
     456                 :            :                                         for (i = 0; i < e->size; ++i)
     457                 :            :                                                 masked[i] = e->magic[i] & e->mask[i];
     458                 :            :                                         print_hex_dump_bytes(
     459                 :            :                                                 KBUILD_MODNAME ": register:  magic[masked]: ",
     460                 :            :                                                 DUMP_PREFIX_NONE, masked, e->size);
     461                 :            : 
     462                 :            :                                         kfree(masked);
     463                 :            :                                 }
     464                 :            :                         }
     465                 :            :                 }
     466                 :            :         } else {
     467                 :            :                 /* Handle the 'E' (extension) format. */
     468                 :            : 
     469                 :            :                 /* Skip the 'offset' field. */
     470                 :          0 :                 p = strchr(p, del);
     471         [ #  # ]:          0 :                 if (!p)
     472                 :          0 :                         goto einval;
     473                 :          0 :                 *p++ = '\0';
     474                 :            : 
     475                 :            :                 /* Parse the 'magic' field. */
     476                 :          0 :                 e->magic = p;
     477                 :          0 :                 p = strchr(p, del);
     478         [ #  # ]:          0 :                 if (!p)
     479                 :          0 :                         goto einval;
     480                 :          0 :                 *p++ = '\0';
     481   [ #  #  #  # ]:          0 :                 if (!e->magic[0] || strchr(e->magic, '/'))
     482                 :          0 :                         goto einval;
     483                 :          0 :                 pr_debug("register: extension: {%s}\n", e->magic);
     484                 :            : 
     485                 :            :                 /* Skip the 'mask' field. */
     486                 :          0 :                 p = strchr(p, del);
     487         [ #  # ]:          0 :                 if (!p)
     488                 :          0 :                         goto einval;
     489                 :          0 :                 *p++ = '\0';
     490                 :            :         }
     491                 :            : 
     492                 :            :         /* Parse the 'interpreter' field. */
     493                 :          0 :         e->interpreter = p;
     494                 :          0 :         p = strchr(p, del);
     495         [ #  # ]:          0 :         if (!p)
     496                 :          0 :                 goto einval;
     497                 :          0 :         *p++ = '\0';
     498         [ #  # ]:          0 :         if (!e->interpreter[0])
     499                 :          0 :                 goto einval;
     500                 :          0 :         pr_debug("register: interpreter: {%s}\n", e->interpreter);
     501                 :            : 
     502                 :            :         /* Parse the 'flags' field. */
     503                 :          0 :         p = check_special_flags(p, e);
     504         [ #  # ]:          0 :         if (*p == '\n')
     505                 :          0 :                 p++;
     506         [ #  # ]:          0 :         if (p != buf + count)
     507                 :          0 :                 goto einval;
     508                 :            : 
     509                 :            :         return e;
     510                 :            : 
     511                 :          0 : out:
     512                 :          0 :         return ERR_PTR(err);
     513                 :            : 
     514                 :            : efault:
     515                 :          0 :         kfree(e);
     516                 :          0 :         return ERR_PTR(-EFAULT);
     517                 :          0 : einval:
     518                 :          0 :         kfree(e);
     519                 :          0 :         return ERR_PTR(-EINVAL);
     520                 :            : }
     521                 :            : 
     522                 :            : /*
     523                 :            :  * Set status of entry/binfmt_misc:
     524                 :            :  * '1' enables, '0' disables and '-1' clears entry/binfmt_misc
     525                 :            :  */
     526                 :          0 : static int parse_command(const char __user *buffer, size_t count)
     527                 :            : {
     528                 :          0 :         char s[4];
     529                 :            : 
     530         [ #  # ]:          0 :         if (count > 3)
     531                 :            :                 return -EINVAL;
     532   [ #  #  #  # ]:          0 :         if (copy_from_user(s, buffer, count))
     533                 :            :                 return -EFAULT;
     534         [ #  # ]:          0 :         if (!count)
     535                 :            :                 return 0;
     536         [ #  # ]:          0 :         if (s[count - 1] == '\n')
     537                 :          0 :                 count--;
     538   [ #  #  #  # ]:          0 :         if (count == 1 && s[0] == '0')
     539                 :            :                 return 1;
     540   [ #  #  #  # ]:          0 :         if (count == 1 && s[0] == '1')
     541                 :            :                 return 2;
     542   [ #  #  #  #  :          0 :         if (count == 2 && s[0] == '-' && s[1] == '1')
                   #  # ]
     543                 :          0 :                 return 3;
     544                 :            :         return -EINVAL;
     545                 :            : }
     546                 :            : 
     547                 :            : /* generic stuff */
     548                 :            : 
     549                 :          0 : static void entry_status(Node *e, char *page)
     550                 :            : {
     551                 :          0 :         char *dp = page;
     552                 :          0 :         const char *status = "disabled";
     553                 :            : 
     554         [ #  # ]:          0 :         if (test_bit(Enabled, &e->flags))
     555                 :          0 :                 status = "enabled";
     556                 :            : 
     557                 :          0 :         if (!VERBOSE_STATUS) {
     558                 :            :                 sprintf(page, "%s\n", status);
     559                 :            :                 return;
     560                 :            :         }
     561                 :            : 
     562                 :          0 :         dp += sprintf(dp, "%s\ninterpreter %s\n", status, e->interpreter);
     563                 :            : 
     564                 :            :         /* print the special flags */
     565                 :          0 :         dp += sprintf(dp, "flags: ");
     566         [ #  # ]:          0 :         if (e->flags & MISC_FMT_PRESERVE_ARGV0)
     567                 :          0 :                 *dp++ = 'P';
     568         [ #  # ]:          0 :         if (e->flags & MISC_FMT_OPEN_BINARY)
     569                 :          0 :                 *dp++ = 'O';
     570         [ #  # ]:          0 :         if (e->flags & MISC_FMT_CREDENTIALS)
     571                 :          0 :                 *dp++ = 'C';
     572         [ #  # ]:          0 :         if (e->flags & MISC_FMT_OPEN_FILE)
     573                 :          0 :                 *dp++ = 'F';
     574                 :          0 :         *dp++ = '\n';
     575                 :            : 
     576         [ #  # ]:          0 :         if (!test_bit(Magic, &e->flags)) {
     577                 :          0 :                 sprintf(dp, "extension .%s\n", e->magic);
     578                 :            :         } else {
     579                 :          0 :                 dp += sprintf(dp, "offset %i\nmagic ", e->offset);
     580                 :          0 :                 dp = bin2hex(dp, e->magic, e->size);
     581         [ #  # ]:          0 :                 if (e->mask) {
     582                 :          0 :                         dp += sprintf(dp, "\nmask ");
     583                 :          0 :                         dp = bin2hex(dp, e->mask, e->size);
     584                 :            :                 }
     585                 :          0 :                 *dp++ = '\n';
     586                 :          0 :                 *dp = '\0';
     587                 :            :         }
     588                 :            : }
     589                 :            : 
     590                 :          0 : static struct inode *bm_get_inode(struct super_block *sb, int mode)
     591                 :            : {
     592                 :          0 :         struct inode *inode = new_inode(sb);
     593                 :            : 
     594         [ #  # ]:          0 :         if (inode) {
     595                 :          0 :                 inode->i_ino = get_next_ino();
     596                 :          0 :                 inode->i_mode = mode;
     597                 :          0 :                 inode->i_atime = inode->i_mtime = inode->i_ctime =
     598                 :          0 :                         current_time(inode);
     599                 :            :         }
     600                 :          0 :         return inode;
     601                 :            : }
     602                 :            : 
     603                 :          0 : static void bm_evict_inode(struct inode *inode)
     604                 :            : {
     605                 :          0 :         Node *e = inode->i_private;
     606                 :            : 
     607   [ #  #  #  # ]:          0 :         if (e && e->flags & MISC_FMT_OPEN_FILE)
     608                 :          0 :                 filp_close(e->interp_file, NULL);
     609                 :            : 
     610                 :          0 :         clear_inode(inode);
     611                 :          0 :         kfree(e);
     612                 :          0 : }
     613                 :            : 
     614                 :          0 : static void kill_node(Node *e)
     615                 :            : {
     616                 :          0 :         struct dentry *dentry;
     617                 :            : 
     618                 :          0 :         write_lock(&entries_lock);
     619                 :          0 :         list_del_init(&e->list);
     620                 :          0 :         write_unlock(&entries_lock);
     621                 :            : 
     622                 :          0 :         dentry = e->dentry;
     623                 :          0 :         drop_nlink(d_inode(dentry));
     624                 :          0 :         d_drop(dentry);
     625                 :          0 :         dput(dentry);
     626                 :          0 :         simple_release_fs(&bm_mnt, &entry_count);
     627                 :          0 : }
     628                 :            : 
     629                 :            : /* /<entry> */
     630                 :            : 
     631                 :            : static ssize_t
     632                 :          0 : bm_entry_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
     633                 :            : {
     634                 :          0 :         Node *e = file_inode(file)->i_private;
     635                 :          0 :         ssize_t res;
     636                 :          0 :         char *page;
     637                 :            : 
     638                 :          0 :         page = (char *) __get_free_page(GFP_KERNEL);
     639         [ #  # ]:          0 :         if (!page)
     640                 :            :                 return -ENOMEM;
     641                 :            : 
     642                 :          0 :         entry_status(e, page);
     643                 :            : 
     644                 :          0 :         res = simple_read_from_buffer(buf, nbytes, ppos, page, strlen(page));
     645                 :            : 
     646                 :          0 :         free_page((unsigned long) page);
     647                 :          0 :         return res;
     648                 :            : }
     649                 :            : 
     650                 :          0 : static ssize_t bm_entry_write(struct file *file, const char __user *buffer,
     651                 :            :                                 size_t count, loff_t *ppos)
     652                 :            : {
     653                 :          0 :         struct dentry *root;
     654                 :          0 :         Node *e = file_inode(file)->i_private;
     655                 :          0 :         int res = parse_command(buffer, count);
     656                 :            : 
     657   [ #  #  #  # ]:          0 :         switch (res) {
     658                 :          0 :         case 1:
     659                 :            :                 /* Disable this handler. */
     660                 :          0 :                 clear_bit(Enabled, &e->flags);
     661                 :          0 :                 break;
     662                 :          0 :         case 2:
     663                 :            :                 /* Enable this handler. */
     664                 :          0 :                 set_bit(Enabled, &e->flags);
     665                 :          0 :                 break;
     666                 :          0 :         case 3:
     667                 :            :                 /* Delete this handler. */
     668                 :          0 :                 root = file_inode(file)->i_sb->s_root;
     669                 :          0 :                 inode_lock(d_inode(root));
     670                 :            : 
     671         [ #  # ]:          0 :                 if (!list_empty(&e->list))
     672                 :          0 :                         kill_node(e);
     673                 :            : 
     674                 :          0 :                 inode_unlock(d_inode(root));
     675                 :            :                 break;
     676                 :          0 :         default:
     677                 :          0 :                 return res;
     678                 :            :         }
     679                 :            : 
     680                 :          0 :         return count;
     681                 :            : }
     682                 :            : 
     683                 :            : static const struct file_operations bm_entry_operations = {
     684                 :            :         .read           = bm_entry_read,
     685                 :            :         .write          = bm_entry_write,
     686                 :            :         .llseek         = default_llseek,
     687                 :            : };
     688                 :            : 
     689                 :            : /* /register */
     690                 :            : 
     691                 :          0 : static ssize_t bm_register_write(struct file *file, const char __user *buffer,
     692                 :            :                                size_t count, loff_t *ppos)
     693                 :            : {
     694                 :          0 :         Node *e;
     695                 :          0 :         struct inode *inode;
     696                 :          0 :         struct super_block *sb = file_inode(file)->i_sb;
     697                 :          0 :         struct dentry *root = sb->s_root, *dentry;
     698                 :          0 :         int err = 0;
     699                 :            : 
     700                 :          0 :         e = create_entry(buffer, count);
     701                 :            : 
     702         [ #  # ]:          0 :         if (IS_ERR(e))
     703                 :          0 :                 return PTR_ERR(e);
     704                 :            : 
     705                 :          0 :         inode_lock(d_inode(root));
     706                 :          0 :         dentry = lookup_one_len(e->name, root, strlen(e->name));
     707         [ #  # ]:          0 :         err = PTR_ERR(dentry);
     708         [ #  # ]:          0 :         if (IS_ERR(dentry))
     709                 :          0 :                 goto out;
     710                 :            : 
     711                 :          0 :         err = -EEXIST;
     712         [ #  # ]:          0 :         if (d_really_is_positive(dentry))
     713                 :          0 :                 goto out2;
     714                 :            : 
     715                 :          0 :         inode = bm_get_inode(sb, S_IFREG | 0644);
     716                 :            : 
     717                 :          0 :         err = -ENOMEM;
     718         [ #  # ]:          0 :         if (!inode)
     719                 :          0 :                 goto out2;
     720                 :            : 
     721                 :          0 :         err = simple_pin_fs(&bm_fs_type, &bm_mnt, &entry_count);
     722         [ #  # ]:          0 :         if (err) {
     723                 :          0 :                 iput(inode);
     724                 :          0 :                 inode = NULL;
     725                 :          0 :                 goto out2;
     726                 :            :         }
     727                 :            : 
     728         [ #  # ]:          0 :         if (e->flags & MISC_FMT_OPEN_FILE) {
     729                 :          0 :                 struct file *f;
     730                 :            : 
     731                 :          0 :                 f = open_exec(e->interpreter);
     732         [ #  # ]:          0 :                 if (IS_ERR(f)) {
     733                 :          0 :                         err = PTR_ERR(f);
     734                 :          0 :                         pr_notice("register: failed to install interpreter file %s\n", e->interpreter);
     735                 :          0 :                         simple_release_fs(&bm_mnt, &entry_count);
     736                 :          0 :                         iput(inode);
     737                 :          0 :                         inode = NULL;
     738                 :          0 :                         goto out2;
     739                 :            :                 }
     740                 :          0 :                 e->interp_file = f;
     741                 :            :         }
     742                 :            : 
     743         [ #  # ]:          0 :         e->dentry = dget(dentry);
     744                 :          0 :         inode->i_private = e;
     745                 :          0 :         inode->i_fop = &bm_entry_operations;
     746                 :            : 
     747                 :          0 :         d_instantiate(dentry, inode);
     748                 :          0 :         write_lock(&entries_lock);
     749                 :          0 :         list_add(&e->list, &entries);
     750                 :          0 :         write_unlock(&entries_lock);
     751                 :            : 
     752                 :          0 :         err = 0;
     753                 :          0 : out2:
     754                 :          0 :         dput(dentry);
     755                 :          0 : out:
     756                 :          0 :         inode_unlock(d_inode(root));
     757                 :            : 
     758         [ #  # ]:          0 :         if (err) {
     759                 :          0 :                 kfree(e);
     760                 :          0 :                 return err;
     761                 :            :         }
     762                 :          0 :         return count;
     763                 :            : }
     764                 :            : 
     765                 :            : static const struct file_operations bm_register_operations = {
     766                 :            :         .write          = bm_register_write,
     767                 :            :         .llseek         = noop_llseek,
     768                 :            : };
     769                 :            : 
     770                 :            : /* /status */
     771                 :            : 
     772                 :            : static ssize_t
     773                 :          0 : bm_status_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
     774                 :            : {
     775         [ #  # ]:          0 :         char *s = enabled ? "enabled\n" : "disabled\n";
     776                 :            : 
     777                 :          0 :         return simple_read_from_buffer(buf, nbytes, ppos, s, strlen(s));
     778                 :            : }
     779                 :            : 
     780                 :          0 : static ssize_t bm_status_write(struct file *file, const char __user *buffer,
     781                 :            :                 size_t count, loff_t *ppos)
     782                 :            : {
     783                 :          0 :         int res = parse_command(buffer, count);
     784                 :          0 :         struct dentry *root;
     785                 :            : 
     786   [ #  #  #  # ]:          0 :         switch (res) {
     787                 :          0 :         case 1:
     788                 :            :                 /* Disable all handlers. */
     789                 :          0 :                 enabled = 0;
     790                 :          0 :                 break;
     791                 :          0 :         case 2:
     792                 :            :                 /* Enable all handlers. */
     793                 :          0 :                 enabled = 1;
     794                 :          0 :                 break;
     795                 :          0 :         case 3:
     796                 :            :                 /* Delete all handlers. */
     797                 :          0 :                 root = file_inode(file)->i_sb->s_root;
     798                 :          0 :                 inode_lock(d_inode(root));
     799                 :            : 
     800         [ #  # ]:          0 :                 while (!list_empty(&entries))
     801                 :          0 :                         kill_node(list_first_entry(&entries, Node, list));
     802                 :            : 
     803                 :          0 :                 inode_unlock(d_inode(root));
     804                 :            :                 break;
     805                 :          0 :         default:
     806                 :          0 :                 return res;
     807                 :            :         }
     808                 :            : 
     809                 :          0 :         return count;
     810                 :            : }
     811                 :            : 
     812                 :            : static const struct file_operations bm_status_operations = {
     813                 :            :         .read           = bm_status_read,
     814                 :            :         .write          = bm_status_write,
     815                 :            :         .llseek         = default_llseek,
     816                 :            : };
     817                 :            : 
     818                 :            : /* Superblock handling */
     819                 :            : 
     820                 :            : static const struct super_operations s_ops = {
     821                 :            :         .statfs         = simple_statfs,
     822                 :            :         .evict_inode    = bm_evict_inode,
     823                 :            : };
     824                 :            : 
     825                 :          3 : static int bm_fill_super(struct super_block *sb, struct fs_context *fc)
     826                 :            : {
     827                 :          3 :         int err;
     828                 :          3 :         static const struct tree_descr bm_files[] = {
     829                 :            :                 [2] = {"status", &bm_status_operations, S_IWUSR|S_IRUGO},
     830                 :            :                 [3] = {"register", &bm_register_operations, S_IWUSR},
     831                 :            :                 /* last one */ {""}
     832                 :            :         };
     833                 :            : 
     834                 :          3 :         err = simple_fill_super(sb, BINFMTFS_MAGIC, bm_files);
     835         [ +  - ]:          3 :         if (!err)
     836                 :          3 :                 sb->s_op = &s_ops;
     837                 :          3 :         return err;
     838                 :            : }
     839                 :            : 
     840                 :          3 : static int bm_get_tree(struct fs_context *fc)
     841                 :            : {
     842                 :          3 :         return get_tree_single(fc, bm_fill_super);
     843                 :            : }
     844                 :            : 
     845                 :            : static const struct fs_context_operations bm_context_ops = {
     846                 :            :         .get_tree       = bm_get_tree,
     847                 :            : };
     848                 :            : 
     849                 :          3 : static int bm_init_fs_context(struct fs_context *fc)
     850                 :            : {
     851                 :          3 :         fc->ops = &bm_context_ops;
     852                 :          3 :         return 0;
     853                 :            : }
     854                 :            : 
     855                 :            : static struct linux_binfmt misc_format = {
     856                 :            :         .module = THIS_MODULE,
     857                 :            :         .load_binary = load_misc_binary,
     858                 :            : };
     859                 :            : 
     860                 :            : static struct file_system_type bm_fs_type = {
     861                 :            :         .owner          = THIS_MODULE,
     862                 :            :         .name           = "binfmt_misc",
     863                 :            :         .init_fs_context = bm_init_fs_context,
     864                 :            :         .kill_sb        = kill_litter_super,
     865                 :            : };
     866                 :            : MODULE_ALIAS_FS("binfmt_misc");
     867                 :            : 
     868                 :          3 : static int __init init_misc_binfmt(void)
     869                 :            : {
     870                 :          3 :         int err = register_filesystem(&bm_fs_type);
     871         [ +  - ]:          3 :         if (!err)
     872                 :          3 :                 insert_binfmt(&misc_format);
     873                 :          3 :         return err;
     874                 :            : }
     875                 :            : 
     876                 :          0 : static void __exit exit_misc_binfmt(void)
     877                 :            : {
     878                 :          0 :         unregister_binfmt(&misc_format);
     879                 :          0 :         unregister_filesystem(&bm_fs_type);
     880                 :          0 : }
     881                 :            : 
     882                 :            : core_initcall(init_misc_binfmt);
     883                 :            : module_exit(exit_misc_binfmt);
     884                 :            : MODULE_LICENSE("GPL");

Generated by: LCOV version 1.14