Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.15 761 lines 18 kB view raw
1/* 2 * Copyright 2008 Red Hat, Inc. All rights reserved. 3 * Copyright 2008 Ian Kent <raven@themaw.net> 4 * 5 * This file is part of the Linux kernel and is made available under 6 * the terms of the GNU General Public License, version 2, or at your 7 * option, any later version, incorporated herein by reference. 8 */ 9 10#include <linux/module.h> 11#include <linux/vmalloc.h> 12#include <linux/miscdevice.h> 13#include <linux/init.h> 14#include <linux/wait.h> 15#include <linux/namei.h> 16#include <linux/fcntl.h> 17#include <linux/file.h> 18#include <linux/fdtable.h> 19#include <linux/sched.h> 20#include <linux/cred.h> 21#include <linux/compat.h> 22#include <linux/syscalls.h> 23#include <linux/magic.h> 24#include <linux/dcache.h> 25#include <linux/uaccess.h> 26#include <linux/slab.h> 27 28#include "autofs_i.h" 29 30/* 31 * This module implements an interface for routing autofs ioctl control 32 * commands via a miscellaneous device file. 33 * 34 * The alternate interface is needed because we need to be able open 35 * an ioctl file descriptor on an autofs mount that may be covered by 36 * another mount. This situation arises when starting automount(8) 37 * or other user space daemon which uses direct mounts or offset 38 * mounts (used for autofs lazy mount/umount of nested mount trees), 39 * which have been left busy at at service shutdown. 40 */ 41 42typedef int (*ioctl_fn)(struct file *, struct autofs_sb_info *, 43 struct autofs_dev_ioctl *); 44 45static int check_name(const char *name) 46{ 47 if (!strchr(name, '/')) 48 return -EINVAL; 49 return 0; 50} 51 52/* 53 * Check a string doesn't overrun the chunk of 54 * memory we copied from user land. 55 */ 56static int invalid_str(char *str, size_t size) 57{ 58 if (memchr(str, 0, size)) 59 return 0; 60 return -EINVAL; 61} 62 63/* 64 * Check that the user compiled against correct version of autofs 65 * misc device code. 66 * 67 * As well as checking the version compatibility this always copies 68 * the kernel interface version out. 69 */ 70static int check_dev_ioctl_version(int cmd, struct autofs_dev_ioctl *param) 71{ 72 int err = 0; 73 74 if ((param->ver_major != AUTOFS_DEV_IOCTL_VERSION_MAJOR) || 75 (param->ver_minor > AUTOFS_DEV_IOCTL_VERSION_MINOR)) { 76 pr_warn("ioctl control interface version mismatch: " 77 "kernel(%u.%u), user(%u.%u), cmd(0x%08x)\n", 78 AUTOFS_DEV_IOCTL_VERSION_MAJOR, 79 AUTOFS_DEV_IOCTL_VERSION_MINOR, 80 param->ver_major, param->ver_minor, cmd); 81 err = -EINVAL; 82 } 83 84 /* Fill in the kernel version. */ 85 param->ver_major = AUTOFS_DEV_IOCTL_VERSION_MAJOR; 86 param->ver_minor = AUTOFS_DEV_IOCTL_VERSION_MINOR; 87 88 return err; 89} 90 91/* 92 * Copy parameter control struct, including a possible path allocated 93 * at the end of the struct. 94 */ 95static struct autofs_dev_ioctl * 96copy_dev_ioctl(struct autofs_dev_ioctl __user *in) 97{ 98 struct autofs_dev_ioctl tmp, *res; 99 100 if (copy_from_user(&tmp, in, AUTOFS_DEV_IOCTL_SIZE)) 101 return ERR_PTR(-EFAULT); 102 103 if (tmp.size < AUTOFS_DEV_IOCTL_SIZE) 104 return ERR_PTR(-EINVAL); 105 106 if (tmp.size > AUTOFS_DEV_IOCTL_SIZE + PATH_MAX) 107 return ERR_PTR(-ENAMETOOLONG); 108 109 res = memdup_user(in, tmp.size); 110 if (!IS_ERR(res)) 111 res->size = tmp.size; 112 113 return res; 114} 115 116static inline void free_dev_ioctl(struct autofs_dev_ioctl *param) 117{ 118 kfree(param); 119} 120 121/* 122 * Check sanity of parameter control fields and if a path is present 123 * check that it is terminated and contains at least one "/". 124 */ 125static int validate_dev_ioctl(int cmd, struct autofs_dev_ioctl *param) 126{ 127 int err; 128 129 err = check_dev_ioctl_version(cmd, param); 130 if (err) { 131 pr_warn("invalid device control module version " 132 "supplied for cmd(0x%08x)\n", cmd); 133 goto out; 134 } 135 136 if (param->size > AUTOFS_DEV_IOCTL_SIZE) { 137 err = invalid_str(param->path, param->size - AUTOFS_DEV_IOCTL_SIZE); 138 if (err) { 139 pr_warn( 140 "path string terminator missing for cmd(0x%08x)\n", 141 cmd); 142 goto out; 143 } 144 145 err = check_name(param->path); 146 if (err) { 147 pr_warn("invalid path supplied for cmd(0x%08x)\n", 148 cmd); 149 goto out; 150 } 151 } 152 153 err = 0; 154out: 155 return err; 156} 157 158/* 159 * Get the autofs super block info struct from the file opened on 160 * the autofs mount point. 161 */ 162static struct autofs_sb_info *autofs_dev_ioctl_sbi(struct file *f) 163{ 164 struct autofs_sb_info *sbi = NULL; 165 struct inode *inode; 166 167 if (f) { 168 inode = file_inode(f); 169 sbi = autofs4_sbi(inode->i_sb); 170 } 171 return sbi; 172} 173 174/* Return autofs dev ioctl version */ 175static int autofs_dev_ioctl_version(struct file *fp, 176 struct autofs_sb_info *sbi, 177 struct autofs_dev_ioctl *param) 178{ 179 /* This should have already been set. */ 180 param->ver_major = AUTOFS_DEV_IOCTL_VERSION_MAJOR; 181 param->ver_minor = AUTOFS_DEV_IOCTL_VERSION_MINOR; 182 return 0; 183} 184 185/* Return autofs module protocol version */ 186static int autofs_dev_ioctl_protover(struct file *fp, 187 struct autofs_sb_info *sbi, 188 struct autofs_dev_ioctl *param) 189{ 190 param->protover.version = sbi->version; 191 return 0; 192} 193 194/* Return autofs module protocol sub version */ 195static int autofs_dev_ioctl_protosubver(struct file *fp, 196 struct autofs_sb_info *sbi, 197 struct autofs_dev_ioctl *param) 198{ 199 param->protosubver.sub_version = sbi->sub_version; 200 return 0; 201} 202 203/* Find the topmost mount satisfying test() */ 204static int find_autofs_mount(const char *pathname, 205 struct path *res, 206 int test(const struct path *path, void *data), 207 void *data) 208{ 209 struct path path; 210 int err; 211 212 err = kern_path_mountpoint(AT_FDCWD, pathname, &path, 0); 213 if (err) 214 return err; 215 err = -ENOENT; 216 while (path.dentry == path.mnt->mnt_root) { 217 if (path.dentry->d_sb->s_magic == AUTOFS_SUPER_MAGIC) { 218 if (test(&path, data)) { 219 path_get(&path); 220 *res = path; 221 err = 0; 222 break; 223 } 224 } 225 if (!follow_up(&path)) 226 break; 227 } 228 path_put(&path); 229 return err; 230} 231 232static int test_by_dev(const struct path *path, void *p) 233{ 234 return path->dentry->d_sb->s_dev == *(dev_t *)p; 235} 236 237static int test_by_type(const struct path *path, void *p) 238{ 239 struct autofs_info *ino = autofs4_dentry_ino(path->dentry); 240 241 return ino && ino->sbi->type & *(unsigned *)p; 242} 243 244/* 245 * Open a file descriptor on the autofs mount point corresponding 246 * to the given path and device number (aka. new_encode_dev(sb->s_dev)). 247 */ 248static int autofs_dev_ioctl_open_mountpoint(const char *name, dev_t devid) 249{ 250 int err, fd; 251 252 fd = get_unused_fd_flags(O_CLOEXEC); 253 if (likely(fd >= 0)) { 254 struct file *filp; 255 struct path path; 256 257 err = find_autofs_mount(name, &path, test_by_dev, &devid); 258 if (err) 259 goto out; 260 261 filp = dentry_open(&path, O_RDONLY, current_cred()); 262 path_put(&path); 263 if (IS_ERR(filp)) { 264 err = PTR_ERR(filp); 265 goto out; 266 } 267 268 fd_install(fd, filp); 269 } 270 271 return fd; 272 273out: 274 put_unused_fd(fd); 275 return err; 276} 277 278/* Open a file descriptor on an autofs mount point */ 279static int autofs_dev_ioctl_openmount(struct file *fp, 280 struct autofs_sb_info *sbi, 281 struct autofs_dev_ioctl *param) 282{ 283 const char *path; 284 dev_t devid; 285 int err, fd; 286 287 /* param->path has already been checked */ 288 if (!param->openmount.devid) 289 return -EINVAL; 290 291 param->ioctlfd = -1; 292 293 path = param->path; 294 devid = new_decode_dev(param->openmount.devid); 295 296 err = 0; 297 fd = autofs_dev_ioctl_open_mountpoint(path, devid); 298 if (unlikely(fd < 0)) { 299 err = fd; 300 goto out; 301 } 302 303 param->ioctlfd = fd; 304out: 305 return err; 306} 307 308/* Close file descriptor allocated above (user can also use close(2)). */ 309static int autofs_dev_ioctl_closemount(struct file *fp, 310 struct autofs_sb_info *sbi, 311 struct autofs_dev_ioctl *param) 312{ 313 return sys_close(param->ioctlfd); 314} 315 316/* 317 * Send "ready" status for an existing wait (either a mount or an expire 318 * request). 319 */ 320static int autofs_dev_ioctl_ready(struct file *fp, 321 struct autofs_sb_info *sbi, 322 struct autofs_dev_ioctl *param) 323{ 324 autofs_wqt_t token; 325 326 token = (autofs_wqt_t) param->ready.token; 327 return autofs4_wait_release(sbi, token, 0); 328} 329 330/* 331 * Send "fail" status for an existing wait (either a mount or an expire 332 * request). 333 */ 334static int autofs_dev_ioctl_fail(struct file *fp, 335 struct autofs_sb_info *sbi, 336 struct autofs_dev_ioctl *param) 337{ 338 autofs_wqt_t token; 339 int status; 340 341 token = (autofs_wqt_t) param->fail.token; 342 status = param->fail.status < 0 ? param->fail.status : -ENOENT; 343 return autofs4_wait_release(sbi, token, status); 344} 345 346/* 347 * Set the pipe fd for kernel communication to the daemon. 348 * 349 * Normally this is set at mount using an option but if we 350 * are reconnecting to a busy mount then we need to use this 351 * to tell the autofs mount about the new kernel pipe fd. In 352 * order to protect mounts against incorrectly setting the 353 * pipefd we also require that the autofs mount be catatonic. 354 * 355 * This also sets the process group id used to identify the 356 * controlling process (eg. the owning automount(8) daemon). 357 */ 358static int autofs_dev_ioctl_setpipefd(struct file *fp, 359 struct autofs_sb_info *sbi, 360 struct autofs_dev_ioctl *param) 361{ 362 int pipefd; 363 int err = 0; 364 struct pid *new_pid = NULL; 365 366 if (param->setpipefd.pipefd == -1) 367 return -EINVAL; 368 369 pipefd = param->setpipefd.pipefd; 370 371 mutex_lock(&sbi->wq_mutex); 372 if (!sbi->catatonic) { 373 mutex_unlock(&sbi->wq_mutex); 374 return -EBUSY; 375 } else { 376 struct file *pipe; 377 378 new_pid = get_task_pid(current, PIDTYPE_PGID); 379 380 if (ns_of_pid(new_pid) != ns_of_pid(sbi->oz_pgrp)) { 381 pr_warn("not allowed to change PID namespace\n"); 382 err = -EINVAL; 383 goto out; 384 } 385 386 pipe = fget(pipefd); 387 if (!pipe) { 388 err = -EBADF; 389 goto out; 390 } 391 if (autofs_prepare_pipe(pipe) < 0) { 392 err = -EPIPE; 393 fput(pipe); 394 goto out; 395 } 396 swap(sbi->oz_pgrp, new_pid); 397 sbi->pipefd = pipefd; 398 sbi->pipe = pipe; 399 sbi->catatonic = 0; 400 } 401out: 402 put_pid(new_pid); 403 mutex_unlock(&sbi->wq_mutex); 404 return err; 405} 406 407/* 408 * Make the autofs mount point catatonic, no longer responsive to 409 * mount requests. Also closes the kernel pipe file descriptor. 410 */ 411static int autofs_dev_ioctl_catatonic(struct file *fp, 412 struct autofs_sb_info *sbi, 413 struct autofs_dev_ioctl *param) 414{ 415 autofs4_catatonic_mode(sbi); 416 return 0; 417} 418 419/* Set the autofs mount timeout */ 420static int autofs_dev_ioctl_timeout(struct file *fp, 421 struct autofs_sb_info *sbi, 422 struct autofs_dev_ioctl *param) 423{ 424 unsigned long timeout; 425 426 timeout = param->timeout.timeout; 427 param->timeout.timeout = sbi->exp_timeout / HZ; 428 sbi->exp_timeout = timeout * HZ; 429 return 0; 430} 431 432/* 433 * Return the uid and gid of the last request for the mount 434 * 435 * When reconstructing an autofs mount tree with active mounts 436 * we need to re-connect to mounts that may have used the original 437 * process uid and gid (or string variations of them) for mount 438 * lookups within the map entry. 439 */ 440static int autofs_dev_ioctl_requester(struct file *fp, 441 struct autofs_sb_info *sbi, 442 struct autofs_dev_ioctl *param) 443{ 444 struct autofs_info *ino; 445 struct path path; 446 dev_t devid; 447 int err = -ENOENT; 448 449 if (param->size <= AUTOFS_DEV_IOCTL_SIZE) { 450 err = -EINVAL; 451 goto out; 452 } 453 454 devid = sbi->sb->s_dev; 455 456 param->requester.uid = param->requester.gid = -1; 457 458 err = find_autofs_mount(param->path, &path, test_by_dev, &devid); 459 if (err) 460 goto out; 461 462 ino = autofs4_dentry_ino(path.dentry); 463 if (ino) { 464 err = 0; 465 autofs4_expire_wait(&path, 0); 466 spin_lock(&sbi->fs_lock); 467 param->requester.uid = 468 from_kuid_munged(current_user_ns(), ino->uid); 469 param->requester.gid = 470 from_kgid_munged(current_user_ns(), ino->gid); 471 spin_unlock(&sbi->fs_lock); 472 } 473 path_put(&path); 474out: 475 return err; 476} 477 478/* 479 * Call repeatedly until it returns -EAGAIN, meaning there's nothing 480 * more that can be done. 481 */ 482static int autofs_dev_ioctl_expire(struct file *fp, 483 struct autofs_sb_info *sbi, 484 struct autofs_dev_ioctl *param) 485{ 486 struct vfsmount *mnt; 487 int how; 488 489 how = param->expire.how; 490 mnt = fp->f_path.mnt; 491 492 return autofs4_do_expire_multi(sbi->sb, mnt, sbi, how); 493} 494 495/* Check if autofs mount point is in use */ 496static int autofs_dev_ioctl_askumount(struct file *fp, 497 struct autofs_sb_info *sbi, 498 struct autofs_dev_ioctl *param) 499{ 500 param->askumount.may_umount = 0; 501 if (may_umount(fp->f_path.mnt)) 502 param->askumount.may_umount = 1; 503 return 0; 504} 505 506/* 507 * Check if the given path is a mountpoint. 508 * 509 * If we are supplied with the file descriptor of an autofs 510 * mount we're looking for a specific mount. In this case 511 * the path is considered a mountpoint if it is itself a 512 * mountpoint or contains a mount, such as a multi-mount 513 * without a root mount. In this case we return 1 if the 514 * path is a mount point and the super magic of the covering 515 * mount if there is one or 0 if it isn't a mountpoint. 516 * 517 * If we aren't supplied with a file descriptor then we 518 * lookup the path and check if it is the root of a mount. 519 * If a type is given we are looking for a particular autofs 520 * mount and if we don't find a match we return fail. If the 521 * located path is the root of a mount we return 1 along with 522 * the super magic of the mount or 0 otherwise. 523 * 524 * In both cases the the device number (as returned by 525 * new_encode_dev()) is also returned. 526 */ 527static int autofs_dev_ioctl_ismountpoint(struct file *fp, 528 struct autofs_sb_info *sbi, 529 struct autofs_dev_ioctl *param) 530{ 531 struct path path; 532 const char *name; 533 unsigned int type; 534 unsigned int devid, magic; 535 int err = -ENOENT; 536 537 if (param->size <= AUTOFS_DEV_IOCTL_SIZE) { 538 err = -EINVAL; 539 goto out; 540 } 541 542 name = param->path; 543 type = param->ismountpoint.in.type; 544 545 param->ismountpoint.out.devid = devid = 0; 546 param->ismountpoint.out.magic = magic = 0; 547 548 if (!fp || param->ioctlfd == -1) { 549 if (autofs_type_any(type)) 550 err = kern_path_mountpoint(AT_FDCWD, 551 name, &path, LOOKUP_FOLLOW); 552 else 553 err = find_autofs_mount(name, &path, 554 test_by_type, &type); 555 if (err) 556 goto out; 557 devid = new_encode_dev(path.dentry->d_sb->s_dev); 558 err = 0; 559 if (path.mnt->mnt_root == path.dentry) { 560 err = 1; 561 magic = path.dentry->d_sb->s_magic; 562 } 563 } else { 564 dev_t dev = sbi->sb->s_dev; 565 566 err = find_autofs_mount(name, &path, test_by_dev, &dev); 567 if (err) 568 goto out; 569 570 devid = new_encode_dev(dev); 571 572 err = path_has_submounts(&path); 573 574 if (follow_down_one(&path)) 575 magic = path.dentry->d_sb->s_magic; 576 } 577 578 param->ismountpoint.out.devid = devid; 579 param->ismountpoint.out.magic = magic; 580 path_put(&path); 581out: 582 return err; 583} 584 585/* 586 * Our range of ioctl numbers isn't 0 based so we need to shift 587 * the array index by _IOC_NR(AUTOFS_CTL_IOC_FIRST) for the table 588 * lookup. 589 */ 590#define cmd_idx(cmd) (cmd - _IOC_NR(AUTOFS_DEV_IOCTL_IOC_FIRST)) 591 592static ioctl_fn lookup_dev_ioctl(unsigned int cmd) 593{ 594 static ioctl_fn _ioctls[] = { 595 autofs_dev_ioctl_version, 596 autofs_dev_ioctl_protover, 597 autofs_dev_ioctl_protosubver, 598 autofs_dev_ioctl_openmount, 599 autofs_dev_ioctl_closemount, 600 autofs_dev_ioctl_ready, 601 autofs_dev_ioctl_fail, 602 autofs_dev_ioctl_setpipefd, 603 autofs_dev_ioctl_catatonic, 604 autofs_dev_ioctl_timeout, 605 autofs_dev_ioctl_requester, 606 autofs_dev_ioctl_expire, 607 autofs_dev_ioctl_askumount, 608 autofs_dev_ioctl_ismountpoint, 609 }; 610 unsigned int idx = cmd_idx(cmd); 611 612 return (idx >= ARRAY_SIZE(_ioctls)) ? NULL : _ioctls[idx]; 613} 614 615/* ioctl dispatcher */ 616static int _autofs_dev_ioctl(unsigned int command, 617 struct autofs_dev_ioctl __user *user) 618{ 619 struct autofs_dev_ioctl *param; 620 struct file *fp; 621 struct autofs_sb_info *sbi; 622 unsigned int cmd_first, cmd; 623 ioctl_fn fn = NULL; 624 int err = 0; 625 626 cmd_first = _IOC_NR(AUTOFS_DEV_IOCTL_IOC_FIRST); 627 cmd = _IOC_NR(command); 628 629 if (_IOC_TYPE(command) != _IOC_TYPE(AUTOFS_DEV_IOCTL_IOC_FIRST) || 630 cmd - cmd_first > AUTOFS_DEV_IOCTL_IOC_COUNT) { 631 return -ENOTTY; 632 } 633 634 /* Only root can use ioctls other than AUTOFS_DEV_IOCTL_VERSION_CMD 635 * and AUTOFS_DEV_IOCTL_ISMOUNTPOINT_CMD 636 */ 637 if (cmd != AUTOFS_DEV_IOCTL_VERSION_CMD && 638 cmd != AUTOFS_DEV_IOCTL_ISMOUNTPOINT_CMD && 639 !capable(CAP_SYS_ADMIN)) 640 return -EPERM; 641 642 /* Copy the parameters into kernel space. */ 643 param = copy_dev_ioctl(user); 644 if (IS_ERR(param)) 645 return PTR_ERR(param); 646 647 err = validate_dev_ioctl(command, param); 648 if (err) 649 goto out; 650 651 fn = lookup_dev_ioctl(cmd); 652 if (!fn) { 653 pr_warn("unknown command 0x%08x\n", command); 654 err = -ENOTTY; 655 goto out; 656 } 657 658 fp = NULL; 659 sbi = NULL; 660 661 /* 662 * For obvious reasons the openmount can't have a file 663 * descriptor yet. We don't take a reference to the 664 * file during close to allow for immediate release, 665 * and the same for retrieving ioctl version. 666 */ 667 if (cmd != AUTOFS_DEV_IOCTL_VERSION_CMD && 668 cmd != AUTOFS_DEV_IOCTL_OPENMOUNT_CMD && 669 cmd != AUTOFS_DEV_IOCTL_CLOSEMOUNT_CMD) { 670 fp = fget(param->ioctlfd); 671 if (!fp) { 672 if (cmd == AUTOFS_DEV_IOCTL_ISMOUNTPOINT_CMD) 673 goto cont; 674 err = -EBADF; 675 goto out; 676 } 677 678 sbi = autofs_dev_ioctl_sbi(fp); 679 if (!sbi || sbi->magic != AUTOFS_SBI_MAGIC) { 680 err = -EINVAL; 681 fput(fp); 682 goto out; 683 } 684 685 /* 686 * Admin needs to be able to set the mount catatonic in 687 * order to be able to perform the re-open. 688 */ 689 if (!autofs4_oz_mode(sbi) && 690 cmd != AUTOFS_DEV_IOCTL_CATATONIC_CMD) { 691 err = -EACCES; 692 fput(fp); 693 goto out; 694 } 695 } 696cont: 697 err = fn(fp, sbi, param); 698 699 if (fp) 700 fput(fp); 701 if (err >= 0 && copy_to_user(user, param, AUTOFS_DEV_IOCTL_SIZE)) 702 err = -EFAULT; 703out: 704 free_dev_ioctl(param); 705 return err; 706} 707 708static long autofs_dev_ioctl(struct file *file, unsigned int command, 709 unsigned long u) 710{ 711 int err; 712 713 err = _autofs_dev_ioctl(command, (struct autofs_dev_ioctl __user *) u); 714 return (long) err; 715} 716 717#ifdef CONFIG_COMPAT 718static long autofs_dev_ioctl_compat(struct file *file, unsigned int command, 719 unsigned long u) 720{ 721 return autofs_dev_ioctl(file, command, (unsigned long) compat_ptr(u)); 722} 723#else 724#define autofs_dev_ioctl_compat NULL 725#endif 726 727static const struct file_operations _dev_ioctl_fops = { 728 .unlocked_ioctl = autofs_dev_ioctl, 729 .compat_ioctl = autofs_dev_ioctl_compat, 730 .owner = THIS_MODULE, 731 .llseek = noop_llseek, 732}; 733 734static struct miscdevice _autofs_dev_ioctl_misc = { 735 .minor = AUTOFS_MINOR, 736 .name = AUTOFS_DEVICE_NAME, 737 .fops = &_dev_ioctl_fops, 738 .mode = 0644, 739}; 740 741MODULE_ALIAS_MISCDEV(AUTOFS_MINOR); 742MODULE_ALIAS("devname:autofs"); 743 744/* Register/deregister misc character device */ 745int __init autofs_dev_ioctl_init(void) 746{ 747 int r; 748 749 r = misc_register(&_autofs_dev_ioctl_misc); 750 if (r) { 751 pr_err("misc_register failed for control device\n"); 752 return r; 753 } 754 755 return 0; 756} 757 758void autofs_dev_ioctl_exit(void) 759{ 760 misc_deregister(&_autofs_dev_ioctl_misc); 761}