binfmt_misc.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:14k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  *  binfmt_misc.c
  3.  *
  4.  *  Copyright (C) 1997 Richard G黱ther
  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. #include <linux/module.h>
  19. #include <linux/init.h>
  20. #include <linux/binfmts.h>
  21. #include <linux/slab.h>
  22. #include <linux/ctype.h>
  23. #include <linux/file.h>
  24. #include <linux/pagemap.h>
  25. #include <asm/uaccess.h>
  26. enum {
  27. VERBOSE_STATUS = 1 /* make it zero to save 400 bytes kernel memory */
  28. };
  29. static LIST_HEAD(entries);
  30. static int enabled = 1;
  31. enum {Enabled, Magic};
  32. typedef struct {
  33. struct list_head list;
  34. unsigned long flags; /* type, status, etc. */
  35. int offset; /* offset of magic */
  36. int size; /* size of magic/mask */
  37. char *magic; /* magic or filename extension */
  38. char *mask; /* mask, NULL for exact match */
  39. char *interpreter; /* filename of interpreter */
  40. char *name;
  41. struct dentry *dentry;
  42. } Node;
  43. static rwlock_t entries_lock __attribute__((unused)) = RW_LOCK_UNLOCKED;
  44. /* 
  45.  * Check if we support the binfmt
  46.  * if we do, return the node, else NULL
  47.  * locking is done in load_misc_binary
  48.  */
  49. static Node *check_file(struct linux_binprm *bprm)
  50. {
  51. char *p = strrchr(bprm->filename, '.');
  52. struct list_head *l;
  53. for (l = entries.next; l != &entries; l = l->next) {
  54. Node *e = list_entry(l, Node, list);
  55. char *s;
  56. int j;
  57. if (!test_bit(Enabled, &e->flags))
  58. continue;
  59. if (!test_bit(Magic, &e->flags)) {
  60. if (p && !strcmp(e->magic, p + 1))
  61. return e;
  62. continue;
  63. }
  64. s = bprm->buf + e->offset;
  65. if (e->mask) {
  66. for (j = 0; j < e->size; j++)
  67. if ((*s++ ^ e->magic[j]) & e->mask[j])
  68. break;
  69. } else {
  70. for (j = 0; j < e->size; j++)
  71. if ((*s++ ^ e->magic[j]))
  72. break;
  73. }
  74. if (j == e->size)
  75. return e;
  76. }
  77. return NULL;
  78. }
  79. /*
  80.  * the loader itself
  81.  */
  82. static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs)
  83. {
  84. Node *fmt;
  85. struct file * file;
  86. char iname[BINPRM_BUF_SIZE];
  87. char *iname_addr = iname;
  88. int retval;
  89. retval = -ENOEXEC;
  90. if (!enabled)
  91. goto _ret;
  92. /* to keep locking time low, we copy the interpreter string */
  93. read_lock(&entries_lock);
  94. fmt = check_file(bprm);
  95. if (fmt) {
  96. strncpy(iname, fmt->interpreter, BINPRM_BUF_SIZE - 1);
  97. iname[BINPRM_BUF_SIZE - 1] = '';
  98. }
  99. read_unlock(&entries_lock);
  100. if (!fmt)
  101. goto _ret;
  102. allow_write_access(bprm->file);
  103. fput(bprm->file);
  104. bprm->file = NULL;
  105. /* Build args for interpreter */
  106. remove_arg_zero(bprm);
  107. retval = copy_strings_kernel(1, &bprm->filename, bprm);
  108. if (retval < 0) goto _ret; 
  109. bprm->argc++;
  110. retval = copy_strings_kernel(1, &iname_addr, bprm);
  111. if (retval < 0) goto _ret; 
  112. bprm->argc++;
  113. bprm->filename = iname; /* for binfmt_script */
  114. file = open_exec(iname);
  115. retval = PTR_ERR(file);
  116. if (IS_ERR(file))
  117. goto _ret;
  118. bprm->file = file;
  119. retval = prepare_binprm(bprm);
  120. if (retval >= 0)
  121. retval = search_binary_handler(bprm, regs);
  122. _ret:
  123. return retval;
  124. }
  125. /* Command parsers */
  126. /*
  127.  * parses and copies one argument enclosed in del from *sp to *dp,
  128.  * recognising the x special.
  129.  * returns pointer to the copied argument or NULL in case of an
  130.  * error (and sets err) or null argument length.
  131.  */
  132. static char *scanarg(char *s, char del)
  133. {
  134. char c;
  135. while ((c = *s++) != del) {
  136. if (c == '\' && *s == 'x') {
  137. s++;
  138. if (!isxdigit(*s++))
  139. return NULL;
  140. if (!isxdigit(*s++))
  141. return NULL;
  142. }
  143. }
  144. return s;
  145. }
  146. static int unquote(char *from)
  147. {
  148. char c = 0, *s = from, *p = from;
  149. while ((c = *s++) != '') {
  150. if (c == '\' && *s == 'x') {
  151. s++;
  152. c = toupper(*s++);
  153. *p = (c - (isdigit(c) ? '0' : 'A' - 10)) << 4;
  154. c = toupper(*s++);
  155. *p++ |= c - (isdigit(c) ? '0' : 'A' - 10);
  156. continue;
  157. }
  158. *p++ = c;
  159. }
  160. return p - from;
  161. }
  162. /*
  163.  * This registers a new binary format, it recognises the syntax
  164.  * ':name:type:offset:magic:mask:interpreter:'
  165.  * where the ':' is the IFS, that can be chosen with the first char
  166.  */
  167. static Node *create_entry(const char *buffer, size_t count)
  168. {
  169. Node *e;
  170. int memsize, err;
  171. char *buf, *p;
  172. char del;
  173. /* some sanity checks */
  174. err = -EINVAL;
  175. if ((count < 11) || (count > 256))
  176. goto out;
  177. err = -ENOMEM;
  178. memsize = sizeof(Node) + count + 8;
  179. e = (Node *) kmalloc(memsize, GFP_USER);
  180. if (!e)
  181. goto out;
  182. p = buf = (char *)e + sizeof(Node);
  183. memset(e, 0, sizeof(Node));
  184. if (copy_from_user(buf, buffer, count))
  185. goto Efault;
  186. del = *p++; /* delimeter */
  187. memset(buf+count, del, 8);
  188. e->name = p;
  189. p = strchr(p, del);
  190. if (!p)
  191. goto Einval;
  192. *p++ = '';
  193. if (!e->name[0] ||
  194.     !strcmp(e->name, ".") ||
  195.     !strcmp(e->name, "..") ||
  196.     strchr(e->name, '/'))
  197. goto Einval;
  198. switch (*p++) {
  199. case 'E': e->flags = 1<<Enabled; break;
  200. case 'M': e->flags = (1<<Enabled) | (1<<Magic); break;
  201. default: goto Einval;
  202. }
  203. if (*p++ != del)
  204. goto Einval;
  205. if (test_bit(Magic, &e->flags)) {
  206. char *s = strchr(p, del);
  207. if (!s)
  208. goto Einval;
  209. *s++ = '';
  210. e->offset = simple_strtoul(p, &p, 10);
  211. if (*p++)
  212. goto Einval;
  213. e->magic = p;
  214. p = scanarg(p, del);
  215. if (!p)
  216. goto Einval;
  217. p[-1] = '';
  218. if (!e->magic[0])
  219. goto Einval;
  220. e->mask = p;
  221. p = scanarg(p, del);
  222. if (!p)
  223. goto Einval;
  224. p[-1] = '';
  225. if (!e->mask[0])
  226. e->mask = NULL;
  227. e->size = unquote(e->magic);
  228. if (e->mask && unquote(e->mask) != e->size)
  229. goto Einval;
  230. if (e->size + e->offset > BINPRM_BUF_SIZE)
  231. goto Einval;
  232. } else {
  233. p = strchr(p, del);
  234. if (!p)
  235. goto Einval;
  236. *p++ = '';
  237. e->magic = p;
  238. p = strchr(p, del);
  239. if (!p)
  240. goto Einval;
  241. *p++ = '';
  242. if (!e->magic[0] || strchr(e->magic, '/'))
  243. goto Einval;
  244. p = strchr(p, del);
  245. if (!p)
  246. goto Einval;
  247. *p++ = '';
  248. }
  249. e->interpreter = p;
  250. p = strchr(p, del);
  251. if (!p)
  252. goto Einval;
  253. *p++ = '';
  254. if (!e->interpreter[0])
  255. goto Einval;
  256. if (*p == 'n')
  257. p++;
  258. if (p != buf + count)
  259. goto Einval;
  260. return e;
  261. out:
  262. return ERR_PTR(err);
  263. Efault:
  264. kfree(e);
  265. return ERR_PTR(-EFAULT);
  266. Einval:
  267. kfree(e);
  268. return ERR_PTR(-EINVAL);
  269. }
  270. /*
  271.  * Set status of entry/binfmt_misc:
  272.  * '1' enables, '0' disables and '-1' clears entry/binfmt_misc
  273.  */
  274. static int parse_command(const char *buffer, size_t count)
  275. {
  276. char s[4];
  277. if (!count)
  278. return 0;
  279. if (count > 3)
  280. return -EINVAL;
  281. if (copy_from_user(s, buffer, count))
  282. return -EFAULT;
  283. if (s[count-1] == 'n')
  284. count--;
  285. if (count == 1 && s[0] == '0')
  286. return 1;
  287. if (count == 1 && s[0] == '1')
  288. return 2;
  289. if (count == 2 && s[0] == '-' && s[1] == '1')
  290. return 3;
  291. return -EINVAL;
  292. }
  293. /* generic stuff */
  294. static void entry_status(Node *e, char *page)
  295. {
  296. char *dp;
  297. char *status = "disabled";
  298. if (test_bit(Enabled, &e->flags))
  299. status = "enabled";
  300. if (!VERBOSE_STATUS) {
  301. sprintf(page, "%sn", status);
  302. return;
  303. }
  304. sprintf(page, "%sninterpreter %sn", status, e->interpreter);
  305. dp = page + strlen(page);
  306. if (!test_bit(Magic, &e->flags)) {
  307. sprintf(dp, "extension .%sn", e->magic);
  308. } else {
  309. int i;
  310. sprintf(dp, "offset %inmagic ", e->offset);
  311. dp = page + strlen(page);
  312. for (i = 0; i < e->size; i++) {
  313. sprintf(dp, "%02x", 0xff & (int) (e->magic[i]));
  314. dp += 2;
  315. }
  316. if (e->mask) {
  317. sprintf(dp, "nmask ");
  318. dp += 6;
  319. for (i = 0; i < e->size; i++) {
  320. sprintf(dp, "%02x", 0xff & (int) (e->mask[i]));
  321. dp += 2;
  322. }
  323. }
  324. *dp++ = 'n';
  325. *dp = '';
  326. }
  327. }
  328. static struct inode *bm_get_inode(struct super_block *sb, int mode)
  329. {
  330. struct inode * inode = new_inode(sb);
  331. if (inode) {
  332. inode->i_mode = mode;
  333. inode->i_uid = 0;
  334. inode->i_gid = 0;
  335. inode->i_blksize = PAGE_CACHE_SIZE;
  336. inode->i_blocks = 0;
  337. inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
  338. }
  339. return inode;
  340. }
  341. static void bm_clear_inode(struct inode *inode)
  342. {
  343. Node *e = inode->u.generic_ip;
  344. if (e) {
  345. write_lock(&entries_lock);
  346. list_del(&e->list);
  347. write_unlock(&entries_lock);
  348. kfree(e);
  349. }
  350. }
  351. static void kill_node(Node *e)
  352. {
  353. struct dentry *dentry;
  354. write_lock(&entries_lock);
  355. dentry = e->dentry;
  356. if (dentry) {
  357. list_del(&e->list);
  358. INIT_LIST_HEAD(&e->list);
  359. e->dentry = NULL;
  360. }
  361. write_unlock(&entries_lock);
  362. if (dentry) {
  363. dentry->d_inode->i_nlink--;
  364. d_drop(dentry);
  365. dput(dentry);
  366. }
  367. }
  368. /* /<entry> */
  369. static ssize_t
  370. bm_entry_read(struct file * file, char * buf, size_t nbytes, loff_t *ppos)
  371. {
  372. Node *e = file->f_dentry->d_inode->u.generic_ip;
  373. loff_t pos = *ppos;
  374. ssize_t res;
  375. char *page;
  376. int len;
  377. if (!(page = (char*) __get_free_page(GFP_KERNEL)))
  378. return -ENOMEM;
  379. entry_status(e, page);
  380. len = strlen(page);
  381. res = -EINVAL;
  382. if (pos < 0)
  383. goto out;
  384. res = 0;
  385. if (pos >= len)
  386. goto out;
  387. if (len < pos + nbytes)
  388. nbytes = len - pos;
  389. res = -EFAULT;
  390. if (copy_to_user(buf, page + pos, nbytes))
  391. goto out;
  392. *ppos = pos + nbytes;
  393. res = nbytes;
  394. out:
  395. free_page((unsigned long) page);
  396. return res;
  397. }
  398. static ssize_t bm_entry_write(struct file *file, const char *buffer,
  399. size_t count, loff_t *ppos)
  400. {
  401. struct dentry *root;
  402. Node *e = file->f_dentry->d_inode->u.generic_ip;
  403. int res = parse_command(buffer, count);
  404. switch (res) {
  405. case 1: clear_bit(Enabled, &e->flags);
  406. break;
  407. case 2: set_bit(Enabled, &e->flags);
  408. break;
  409. case 3: root = dget(file->f_vfsmnt->mnt_sb->s_root);
  410. down(&root->d_inode->i_sem);
  411. down(&root->d_inode->i_zombie);
  412. kill_node(e);
  413. up(&root->d_inode->i_zombie);
  414. up(&root->d_inode->i_sem);
  415. dput(root);
  416. break;
  417. default: return res;
  418. }
  419. return count;
  420. }
  421. static struct file_operations bm_entry_operations = {
  422. read: bm_entry_read,
  423. write: bm_entry_write,
  424. };
  425. /* /register */
  426. static ssize_t bm_register_write(struct file *file, const char *buffer,
  427.        size_t count, loff_t *ppos)
  428. {
  429. Node *e;
  430. struct dentry *root, *dentry;
  431. struct super_block *sb = file->f_vfsmnt->mnt_sb;
  432. int err = 0;
  433. e = create_entry(buffer, count);
  434. if (IS_ERR(e))
  435. return PTR_ERR(e);
  436. root = dget(sb->s_root);
  437. down(&root->d_inode->i_sem);
  438. dentry = lookup_one_len(e->name, root, strlen(e->name));
  439. err = PTR_ERR(dentry);
  440. if (!IS_ERR(dentry)) {
  441. down(&root->d_inode->i_zombie);
  442. if (dentry->d_inode) {
  443. err = -EEXIST;
  444. } else {
  445. struct inode * inode = bm_get_inode(sb, S_IFREG | 0644);
  446. err = -ENOMEM;
  447. if (inode) {
  448. write_lock(&entries_lock);
  449. e->dentry = dget(dentry);
  450. inode->u.generic_ip = e;
  451. inode->i_fop = &bm_entry_operations;
  452. d_instantiate(dentry, inode);
  453. list_add(&e->list, &entries);
  454. write_unlock(&entries_lock);
  455. err = 0;
  456. }
  457. }
  458. up(&root->d_inode->i_zombie);
  459. dput(dentry);
  460. }
  461. up(&root->d_inode->i_sem);
  462. dput(root);
  463. if (err) {
  464. kfree(e);
  465. return -EINVAL;
  466. }
  467. return count;
  468. }
  469. static struct file_operations bm_register_operations = {
  470. write: bm_register_write,
  471. };
  472. /* /status */
  473. static ssize_t
  474. bm_status_read(struct file * file, char * buf, size_t nbytes, loff_t *ppos)
  475. {
  476. char *s = enabled ? "enabled" : "disabled";
  477. int len = strlen(s);
  478. loff_t pos = *ppos;
  479. if (pos < 0)
  480. return -EINVAL;
  481. if (pos >= len)
  482. return 0;
  483. if (len < pos + nbytes)
  484. nbytes = len - pos;
  485. if (copy_to_user(buf, s + pos, nbytes))
  486. return -EFAULT;
  487. *ppos = pos + nbytes;
  488. return nbytes;
  489. }
  490. static ssize_t bm_status_write(struct file * file, const char * buffer,
  491. size_t count, loff_t *ppos)
  492. {
  493. int res = parse_command(buffer, count);
  494. struct dentry *root;
  495. switch (res) {
  496. case 1: enabled = 0; break;
  497. case 2: enabled = 1; break;
  498. case 3: root = dget(file->f_vfsmnt->mnt_sb->s_root);
  499. down(&root->d_inode->i_sem);
  500. down(&root->d_inode->i_zombie);
  501. while (!list_empty(&entries))
  502. kill_node(list_entry(entries.next, Node, list));
  503. up(&root->d_inode->i_zombie);
  504. up(&root->d_inode->i_sem);
  505. dput(root);
  506. default: return res;
  507. }
  508. return count;
  509. }
  510. static struct file_operations bm_status_operations = {
  511. read: bm_status_read,
  512. write: bm_status_write,
  513. };
  514. /* / */
  515. static struct dentry * bm_lookup(struct inode *dir, struct dentry *dentry)
  516. {
  517. d_add(dentry, NULL);
  518. return NULL;
  519. }
  520. static struct inode_operations bm_dir_inode_operations = {
  521. lookup: bm_lookup,
  522. };
  523. /* Superblock handling */
  524. static int bm_statfs(struct super_block *sb, struct statfs *buf)
  525. {
  526. buf->f_type = sb->s_magic;
  527. buf->f_bsize = PAGE_CACHE_SIZE;
  528. buf->f_namelen = 255;
  529. return 0;
  530. }
  531. static struct super_operations s_ops = {
  532. statfs: bm_statfs,
  533. put_inode: force_delete,
  534. clear_inode: bm_clear_inode,
  535. };
  536. static struct super_block *bm_read_super(struct super_block * sb, void * data, int silent)
  537. {
  538. struct qstr names[2] = {{name:"status"}, {name:"register"}};
  539. struct inode * inode;
  540. struct dentry * dentry[3];
  541. int i;
  542. for (i=0; i<sizeof(names)/sizeof(names[0]); i++) {
  543. names[i].len = strlen(names[i].name);
  544. names[i].hash = full_name_hash(names[i].name, names[i].len);
  545. }
  546. sb->s_blocksize = PAGE_CACHE_SIZE;
  547. sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
  548. sb->s_magic = 0x42494e4d;
  549. sb->s_op = &s_ops;
  550. inode = bm_get_inode(sb, S_IFDIR | 0755);
  551. if (!inode)
  552. return NULL;
  553. inode->i_op = &bm_dir_inode_operations;
  554. inode->i_fop = &dcache_dir_ops;
  555. dentry[0] = d_alloc_root(inode);
  556. if (!dentry[0]) {
  557. iput(inode);
  558. return NULL;
  559. }
  560. dentry[1] = d_alloc(dentry[0], &names[0]);
  561. if (!dentry[1])
  562. goto out1;
  563. dentry[2] = d_alloc(dentry[0], &names[1]);
  564. if (!dentry[2])
  565. goto out2;
  566. inode = bm_get_inode(sb, S_IFREG | 0644);
  567. if (!inode)
  568. goto out3;
  569. inode->i_fop = &bm_status_operations;
  570. d_add(dentry[1], inode);
  571. inode = bm_get_inode(sb, S_IFREG | 0400);
  572. if (!inode)
  573. goto out3;
  574. inode->i_fop = &bm_register_operations;
  575. d_add(dentry[2], inode);
  576. sb->s_root = dentry[0];
  577. return sb;
  578. out3:
  579. dput(dentry[2]);
  580. out2:
  581. dput(dentry[1]);
  582. out1:
  583. dput(dentry[0]);
  584. return NULL;
  585. }
  586. static struct linux_binfmt misc_format = {
  587. NULL, THIS_MODULE, load_misc_binary, NULL, NULL, 0
  588. };
  589. static DECLARE_FSTYPE(bm_fs_type, "binfmt_misc", bm_read_super, FS_SINGLE|FS_LITTER);
  590. static struct vfsmount *bm_mnt;
  591. static int __init init_misc_binfmt(void)
  592. {
  593. int err = register_filesystem(&bm_fs_type);
  594. if (!err) {
  595. bm_mnt = kern_mount(&bm_fs_type);
  596. err = PTR_ERR(bm_mnt);
  597. if (IS_ERR(bm_mnt))
  598. unregister_filesystem(&bm_fs_type);
  599. else {
  600. err = register_binfmt(&misc_format);
  601. if (err) {
  602. unregister_filesystem(&bm_fs_type);
  603. kern_umount(bm_mnt);
  604. }
  605. }
  606. }
  607. return err;
  608. }
  609. static void __exit exit_misc_binfmt(void)
  610. {
  611. unregister_binfmt(&misc_format);
  612. unregister_filesystem(&bm_fs_type);
  613. kern_umount(bm_mnt);
  614. }
  615. EXPORT_NO_SYMBOLS;
  616. module_init(init_misc_binfmt);
  617. module_exit(exit_misc_binfmt);
  618. MODULE_LICENSE("GPL");