Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/fs/binfmt_misc.c
15109 views
1
/*
2
* binfmt_misc.c
3
*
4
* Copyright (C) 1997 Richard Günther
5
*
6
* binfmt_misc detects binaries via a magic or filename extension and invokes
7
* a specified wrapper. This should obsolete binfmt_java, binfmt_em86 and
8
* binfmt_mz.
9
*
10
* 1997-04-25 first version
11
* [...]
12
* 1997-05-19 cleanup
13
* 1997-06-26 hpa: pass the real filename rather than argv[0]
14
* 1997-06-30 minor cleanup
15
* 1997-08-09 removed extension stripping, locking cleanup
16
* 2001-02-28 AV: rewritten into something that resembles C. Original didn't.
17
*/
18
19
#include <linux/module.h>
20
#include <linux/init.h>
21
#include <linux/sched.h>
22
#include <linux/binfmts.h>
23
#include <linux/slab.h>
24
#include <linux/ctype.h>
25
#include <linux/file.h>
26
#include <linux/pagemap.h>
27
#include <linux/namei.h>
28
#include <linux/mount.h>
29
#include <linux/syscalls.h>
30
#include <linux/fs.h>
31
32
#include <asm/uaccess.h>
33
34
enum {
35
VERBOSE_STATUS = 1 /* make it zero to save 400 bytes kernel memory */
36
};
37
38
static LIST_HEAD(entries);
39
static int enabled = 1;
40
41
enum {Enabled, Magic};
42
#define MISC_FMT_PRESERVE_ARGV0 (1<<31)
43
#define MISC_FMT_OPEN_BINARY (1<<30)
44
#define MISC_FMT_CREDENTIALS (1<<29)
45
46
typedef struct {
47
struct list_head list;
48
unsigned long flags; /* type, status, etc. */
49
int offset; /* offset of magic */
50
int size; /* size of magic/mask */
51
char *magic; /* magic or filename extension */
52
char *mask; /* mask, NULL for exact match */
53
char *interpreter; /* filename of interpreter */
54
char *name;
55
struct dentry *dentry;
56
} Node;
57
58
static DEFINE_RWLOCK(entries_lock);
59
static struct file_system_type bm_fs_type;
60
static struct vfsmount *bm_mnt;
61
static int entry_count;
62
63
/*
64
* Check if we support the binfmt
65
* if we do, return the node, else NULL
66
* locking is done in load_misc_binary
67
*/
68
static Node *check_file(struct linux_binprm *bprm)
69
{
70
char *p = strrchr(bprm->interp, '.');
71
struct list_head *l;
72
73
list_for_each(l, &entries) {
74
Node *e = list_entry(l, Node, list);
75
char *s;
76
int j;
77
78
if (!test_bit(Enabled, &e->flags))
79
continue;
80
81
if (!test_bit(Magic, &e->flags)) {
82
if (p && !strcmp(e->magic, p + 1))
83
return e;
84
continue;
85
}
86
87
s = bprm->buf + e->offset;
88
if (e->mask) {
89
for (j = 0; j < e->size; j++)
90
if ((*s++ ^ e->magic[j]) & e->mask[j])
91
break;
92
} else {
93
for (j = 0; j < e->size; j++)
94
if ((*s++ ^ e->magic[j]))
95
break;
96
}
97
if (j == e->size)
98
return e;
99
}
100
return NULL;
101
}
102
103
/*
104
* the loader itself
105
*/
106
static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs)
107
{
108
Node *fmt;
109
struct file * interp_file = NULL;
110
char iname[BINPRM_BUF_SIZE];
111
const char *iname_addr = iname;
112
int retval;
113
int fd_binary = -1;
114
115
retval = -ENOEXEC;
116
if (!enabled)
117
goto _ret;
118
119
retval = -ENOEXEC;
120
if (bprm->recursion_depth > BINPRM_MAX_RECURSION)
121
goto _ret;
122
123
/* to keep locking time low, we copy the interpreter string */
124
read_lock(&entries_lock);
125
fmt = check_file(bprm);
126
if (fmt)
127
strlcpy(iname, fmt->interpreter, BINPRM_BUF_SIZE);
128
read_unlock(&entries_lock);
129
if (!fmt)
130
goto _ret;
131
132
if (!(fmt->flags & MISC_FMT_PRESERVE_ARGV0)) {
133
retval = remove_arg_zero(bprm);
134
if (retval)
135
goto _ret;
136
}
137
138
if (fmt->flags & MISC_FMT_OPEN_BINARY) {
139
140
/* if the binary should be opened on behalf of the
141
* interpreter than keep it open and assign descriptor
142
* to it */
143
fd_binary = get_unused_fd();
144
if (fd_binary < 0) {
145
retval = fd_binary;
146
goto _ret;
147
}
148
fd_install(fd_binary, bprm->file);
149
150
/* if the binary is not readable than enforce mm->dumpable=0
151
regardless of the interpreter's permissions */
152
if (file_permission(bprm->file, MAY_READ))
153
bprm->interp_flags |= BINPRM_FLAGS_ENFORCE_NONDUMP;
154
155
allow_write_access(bprm->file);
156
bprm->file = NULL;
157
158
/* mark the bprm that fd should be passed to interp */
159
bprm->interp_flags |= BINPRM_FLAGS_EXECFD;
160
bprm->interp_data = fd_binary;
161
162
} else {
163
allow_write_access(bprm->file);
164
fput(bprm->file);
165
bprm->file = NULL;
166
}
167
/* make argv[1] be the path to the binary */
168
retval = copy_strings_kernel (1, &bprm->interp, bprm);
169
if (retval < 0)
170
goto _error;
171
bprm->argc++;
172
173
/* add the interp as argv[0] */
174
retval = copy_strings_kernel (1, &iname_addr, bprm);
175
if (retval < 0)
176
goto _error;
177
bprm->argc ++;
178
179
bprm->interp = iname; /* for binfmt_script */
180
181
interp_file = open_exec (iname);
182
retval = PTR_ERR (interp_file);
183
if (IS_ERR (interp_file))
184
goto _error;
185
186
bprm->file = interp_file;
187
if (fmt->flags & MISC_FMT_CREDENTIALS) {
188
/*
189
* No need to call prepare_binprm(), it's already been
190
* done. bprm->buf is stale, update from interp_file.
191
*/
192
memset(bprm->buf, 0, BINPRM_BUF_SIZE);
193
retval = kernel_read(bprm->file, 0, bprm->buf, BINPRM_BUF_SIZE);
194
} else
195
retval = prepare_binprm (bprm);
196
197
if (retval < 0)
198
goto _error;
199
200
bprm->recursion_depth++;
201
202
retval = search_binary_handler (bprm, regs);
203
if (retval < 0)
204
goto _error;
205
206
_ret:
207
return retval;
208
_error:
209
if (fd_binary > 0)
210
sys_close(fd_binary);
211
bprm->interp_flags = 0;
212
bprm->interp_data = 0;
213
goto _ret;
214
}
215
216
/* Command parsers */
217
218
/*
219
* parses and copies one argument enclosed in del from *sp to *dp,
220
* recognising the \x special.
221
* returns pointer to the copied argument or NULL in case of an
222
* error (and sets err) or null argument length.
223
*/
224
static char *scanarg(char *s, char del)
225
{
226
char c;
227
228
while ((c = *s++) != del) {
229
if (c == '\\' && *s == 'x') {
230
s++;
231
if (!isxdigit(*s++))
232
return NULL;
233
if (!isxdigit(*s++))
234
return NULL;
235
}
236
}
237
return s;
238
}
239
240
static int unquote(char *from)
241
{
242
char c = 0, *s = from, *p = from;
243
244
while ((c = *s++) != '\0') {
245
if (c == '\\' && *s == 'x') {
246
s++;
247
c = toupper(*s++);
248
*p = (c - (isdigit(c) ? '0' : 'A' - 10)) << 4;
249
c = toupper(*s++);
250
*p++ |= c - (isdigit(c) ? '0' : 'A' - 10);
251
continue;
252
}
253
*p++ = c;
254
}
255
return p - from;
256
}
257
258
static char * check_special_flags (char * sfs, Node * e)
259
{
260
char * p = sfs;
261
int cont = 1;
262
263
/* special flags */
264
while (cont) {
265
switch (*p) {
266
case 'P':
267
p++;
268
e->flags |= MISC_FMT_PRESERVE_ARGV0;
269
break;
270
case 'O':
271
p++;
272
e->flags |= MISC_FMT_OPEN_BINARY;
273
break;
274
case 'C':
275
p++;
276
/* this flags also implies the
277
open-binary flag */
278
e->flags |= (MISC_FMT_CREDENTIALS |
279
MISC_FMT_OPEN_BINARY);
280
break;
281
default:
282
cont = 0;
283
}
284
}
285
286
return p;
287
}
288
/*
289
* This registers a new binary format, it recognises the syntax
290
* ':name:type:offset:magic:mask:interpreter:flags'
291
* where the ':' is the IFS, that can be chosen with the first char
292
*/
293
static Node *create_entry(const char __user *buffer, size_t count)
294
{
295
Node *e;
296
int memsize, err;
297
char *buf, *p;
298
char del;
299
300
/* some sanity checks */
301
err = -EINVAL;
302
if ((count < 11) || (count > 256))
303
goto out;
304
305
err = -ENOMEM;
306
memsize = sizeof(Node) + count + 8;
307
e = kmalloc(memsize, GFP_USER);
308
if (!e)
309
goto out;
310
311
p = buf = (char *)e + sizeof(Node);
312
313
memset(e, 0, sizeof(Node));
314
if (copy_from_user(buf, buffer, count))
315
goto Efault;
316
317
del = *p++; /* delimeter */
318
319
memset(buf+count, del, 8);
320
321
e->name = p;
322
p = strchr(p, del);
323
if (!p)
324
goto Einval;
325
*p++ = '\0';
326
if (!e->name[0] ||
327
!strcmp(e->name, ".") ||
328
!strcmp(e->name, "..") ||
329
strchr(e->name, '/'))
330
goto Einval;
331
switch (*p++) {
332
case 'E': e->flags = 1<<Enabled; break;
333
case 'M': e->flags = (1<<Enabled) | (1<<Magic); break;
334
default: goto Einval;
335
}
336
if (*p++ != del)
337
goto Einval;
338
if (test_bit(Magic, &e->flags)) {
339
char *s = strchr(p, del);
340
if (!s)
341
goto Einval;
342
*s++ = '\0';
343
e->offset = simple_strtoul(p, &p, 10);
344
if (*p++)
345
goto Einval;
346
e->magic = p;
347
p = scanarg(p, del);
348
if (!p)
349
goto Einval;
350
p[-1] = '\0';
351
if (!e->magic[0])
352
goto Einval;
353
e->mask = p;
354
p = scanarg(p, del);
355
if (!p)
356
goto Einval;
357
p[-1] = '\0';
358
if (!e->mask[0])
359
e->mask = NULL;
360
e->size = unquote(e->magic);
361
if (e->mask && unquote(e->mask) != e->size)
362
goto Einval;
363
if (e->size + e->offset > BINPRM_BUF_SIZE)
364
goto Einval;
365
} else {
366
p = strchr(p, del);
367
if (!p)
368
goto Einval;
369
*p++ = '\0';
370
e->magic = p;
371
p = strchr(p, del);
372
if (!p)
373
goto Einval;
374
*p++ = '\0';
375
if (!e->magic[0] || strchr(e->magic, '/'))
376
goto Einval;
377
p = strchr(p, del);
378
if (!p)
379
goto Einval;
380
*p++ = '\0';
381
}
382
e->interpreter = p;
383
p = strchr(p, del);
384
if (!p)
385
goto Einval;
386
*p++ = '\0';
387
if (!e->interpreter[0])
388
goto Einval;
389
390
391
p = check_special_flags (p, e);
392
393
if (*p == '\n')
394
p++;
395
if (p != buf + count)
396
goto Einval;
397
return e;
398
399
out:
400
return ERR_PTR(err);
401
402
Efault:
403
kfree(e);
404
return ERR_PTR(-EFAULT);
405
Einval:
406
kfree(e);
407
return ERR_PTR(-EINVAL);
408
}
409
410
/*
411
* Set status of entry/binfmt_misc:
412
* '1' enables, '0' disables and '-1' clears entry/binfmt_misc
413
*/
414
static int parse_command(const char __user *buffer, size_t count)
415
{
416
char s[4];
417
418
if (!count)
419
return 0;
420
if (count > 3)
421
return -EINVAL;
422
if (copy_from_user(s, buffer, count))
423
return -EFAULT;
424
if (s[count-1] == '\n')
425
count--;
426
if (count == 1 && s[0] == '0')
427
return 1;
428
if (count == 1 && s[0] == '1')
429
return 2;
430
if (count == 2 && s[0] == '-' && s[1] == '1')
431
return 3;
432
return -EINVAL;
433
}
434
435
/* generic stuff */
436
437
static void entry_status(Node *e, char *page)
438
{
439
char *dp;
440
char *status = "disabled";
441
const char * flags = "flags: ";
442
443
if (test_bit(Enabled, &e->flags))
444
status = "enabled";
445
446
if (!VERBOSE_STATUS) {
447
sprintf(page, "%s\n", status);
448
return;
449
}
450
451
sprintf(page, "%s\ninterpreter %s\n", status, e->interpreter);
452
dp = page + strlen(page);
453
454
/* print the special flags */
455
sprintf (dp, "%s", flags);
456
dp += strlen (flags);
457
if (e->flags & MISC_FMT_PRESERVE_ARGV0) {
458
*dp ++ = 'P';
459
}
460
if (e->flags & MISC_FMT_OPEN_BINARY) {
461
*dp ++ = 'O';
462
}
463
if (e->flags & MISC_FMT_CREDENTIALS) {
464
*dp ++ = 'C';
465
}
466
*dp ++ = '\n';
467
468
469
if (!test_bit(Magic, &e->flags)) {
470
sprintf(dp, "extension .%s\n", e->magic);
471
} else {
472
int i;
473
474
sprintf(dp, "offset %i\nmagic ", e->offset);
475
dp = page + strlen(page);
476
for (i = 0; i < e->size; i++) {
477
sprintf(dp, "%02x", 0xff & (int) (e->magic[i]));
478
dp += 2;
479
}
480
if (e->mask) {
481
sprintf(dp, "\nmask ");
482
dp += 6;
483
for (i = 0; i < e->size; i++) {
484
sprintf(dp, "%02x", 0xff & (int) (e->mask[i]));
485
dp += 2;
486
}
487
}
488
*dp++ = '\n';
489
*dp = '\0';
490
}
491
}
492
493
static struct inode *bm_get_inode(struct super_block *sb, int mode)
494
{
495
struct inode * inode = new_inode(sb);
496
497
if (inode) {
498
inode->i_ino = get_next_ino();
499
inode->i_mode = mode;
500
inode->i_atime = inode->i_mtime = inode->i_ctime =
501
current_fs_time(inode->i_sb);
502
}
503
return inode;
504
}
505
506
static void bm_evict_inode(struct inode *inode)
507
{
508
end_writeback(inode);
509
kfree(inode->i_private);
510
}
511
512
static void kill_node(Node *e)
513
{
514
struct dentry *dentry;
515
516
write_lock(&entries_lock);
517
dentry = e->dentry;
518
if (dentry) {
519
list_del_init(&e->list);
520
e->dentry = NULL;
521
}
522
write_unlock(&entries_lock);
523
524
if (dentry) {
525
dentry->d_inode->i_nlink--;
526
d_drop(dentry);
527
dput(dentry);
528
simple_release_fs(&bm_mnt, &entry_count);
529
}
530
}
531
532
/* /<entry> */
533
534
static ssize_t
535
bm_entry_read(struct file * file, char __user * buf, size_t nbytes, loff_t *ppos)
536
{
537
Node *e = file->f_path.dentry->d_inode->i_private;
538
ssize_t res;
539
char *page;
540
541
if (!(page = (char*) __get_free_page(GFP_KERNEL)))
542
return -ENOMEM;
543
544
entry_status(e, page);
545
546
res = simple_read_from_buffer(buf, nbytes, ppos, page, strlen(page));
547
548
free_page((unsigned long) page);
549
return res;
550
}
551
552
static ssize_t bm_entry_write(struct file *file, const char __user *buffer,
553
size_t count, loff_t *ppos)
554
{
555
struct dentry *root;
556
Node *e = file->f_path.dentry->d_inode->i_private;
557
int res = parse_command(buffer, count);
558
559
switch (res) {
560
case 1: clear_bit(Enabled, &e->flags);
561
break;
562
case 2: set_bit(Enabled, &e->flags);
563
break;
564
case 3: root = dget(file->f_path.mnt->mnt_sb->s_root);
565
mutex_lock(&root->d_inode->i_mutex);
566
567
kill_node(e);
568
569
mutex_unlock(&root->d_inode->i_mutex);
570
dput(root);
571
break;
572
default: return res;
573
}
574
return count;
575
}
576
577
static const struct file_operations bm_entry_operations = {
578
.read = bm_entry_read,
579
.write = bm_entry_write,
580
.llseek = default_llseek,
581
};
582
583
/* /register */
584
585
static ssize_t bm_register_write(struct file *file, const char __user *buffer,
586
size_t count, loff_t *ppos)
587
{
588
Node *e;
589
struct inode *inode;
590
struct dentry *root, *dentry;
591
struct super_block *sb = file->f_path.mnt->mnt_sb;
592
int err = 0;
593
594
e = create_entry(buffer, count);
595
596
if (IS_ERR(e))
597
return PTR_ERR(e);
598
599
root = dget(sb->s_root);
600
mutex_lock(&root->d_inode->i_mutex);
601
dentry = lookup_one_len(e->name, root, strlen(e->name));
602
err = PTR_ERR(dentry);
603
if (IS_ERR(dentry))
604
goto out;
605
606
err = -EEXIST;
607
if (dentry->d_inode)
608
goto out2;
609
610
inode = bm_get_inode(sb, S_IFREG | 0644);
611
612
err = -ENOMEM;
613
if (!inode)
614
goto out2;
615
616
err = simple_pin_fs(&bm_fs_type, &bm_mnt, &entry_count);
617
if (err) {
618
iput(inode);
619
inode = NULL;
620
goto out2;
621
}
622
623
e->dentry = dget(dentry);
624
inode->i_private = e;
625
inode->i_fop = &bm_entry_operations;
626
627
d_instantiate(dentry, inode);
628
write_lock(&entries_lock);
629
list_add(&e->list, &entries);
630
write_unlock(&entries_lock);
631
632
err = 0;
633
out2:
634
dput(dentry);
635
out:
636
mutex_unlock(&root->d_inode->i_mutex);
637
dput(root);
638
639
if (err) {
640
kfree(e);
641
return -EINVAL;
642
}
643
return count;
644
}
645
646
static const struct file_operations bm_register_operations = {
647
.write = bm_register_write,
648
.llseek = noop_llseek,
649
};
650
651
/* /status */
652
653
static ssize_t
654
bm_status_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
655
{
656
char *s = enabled ? "enabled\n" : "disabled\n";
657
658
return simple_read_from_buffer(buf, nbytes, ppos, s, strlen(s));
659
}
660
661
static ssize_t bm_status_write(struct file * file, const char __user * buffer,
662
size_t count, loff_t *ppos)
663
{
664
int res = parse_command(buffer, count);
665
struct dentry *root;
666
667
switch (res) {
668
case 1: enabled = 0; break;
669
case 2: enabled = 1; break;
670
case 3: root = dget(file->f_path.mnt->mnt_sb->s_root);
671
mutex_lock(&root->d_inode->i_mutex);
672
673
while (!list_empty(&entries))
674
kill_node(list_entry(entries.next, Node, list));
675
676
mutex_unlock(&root->d_inode->i_mutex);
677
dput(root);
678
default: return res;
679
}
680
return count;
681
}
682
683
static const struct file_operations bm_status_operations = {
684
.read = bm_status_read,
685
.write = bm_status_write,
686
.llseek = default_llseek,
687
};
688
689
/* Superblock handling */
690
691
static const struct super_operations s_ops = {
692
.statfs = simple_statfs,
693
.evict_inode = bm_evict_inode,
694
};
695
696
static int bm_fill_super(struct super_block * sb, void * data, int silent)
697
{
698
static struct tree_descr bm_files[] = {
699
[2] = {"status", &bm_status_operations, S_IWUSR|S_IRUGO},
700
[3] = {"register", &bm_register_operations, S_IWUSR},
701
/* last one */ {""}
702
};
703
int err = simple_fill_super(sb, 0x42494e4d, bm_files);
704
if (!err)
705
sb->s_op = &s_ops;
706
return err;
707
}
708
709
static struct dentry *bm_mount(struct file_system_type *fs_type,
710
int flags, const char *dev_name, void *data)
711
{
712
return mount_single(fs_type, flags, data, bm_fill_super);
713
}
714
715
static struct linux_binfmt misc_format = {
716
.module = THIS_MODULE,
717
.load_binary = load_misc_binary,
718
};
719
720
static struct file_system_type bm_fs_type = {
721
.owner = THIS_MODULE,
722
.name = "binfmt_misc",
723
.mount = bm_mount,
724
.kill_sb = kill_litter_super,
725
};
726
727
static int __init init_misc_binfmt(void)
728
{
729
int err = register_filesystem(&bm_fs_type);
730
if (!err) {
731
err = insert_binfmt(&misc_format);
732
if (err)
733
unregister_filesystem(&bm_fs_type);
734
}
735
return err;
736
}
737
738
static void __exit exit_misc_binfmt(void)
739
{
740
unregister_binfmt(&misc_format);
741
unregister_filesystem(&bm_fs_type);
742
}
743
744
core_initcall(init_misc_binfmt);
745
module_exit(exit_misc_binfmt);
746
MODULE_LICENSE("GPL");
747
748