···1414#include <linux/sched.h>1515#include <linux/sched/signal.h>1616#include <linux/module.h>1717-#include <linux/compat.h>1817#include <linux/swap.h>1918#include <linux/falloc.h>2019#include <linux/uio.h>2120#include <linux/fs.h>2222-2323-static struct page **fuse_pages_alloc(unsigned int npages, gfp_t flags,2424- struct fuse_page_desc **desc)2525-{2626- struct page **pages;2727-2828- pages = kzalloc(npages * (sizeof(struct page *) +2929- sizeof(struct fuse_page_desc)), flags);3030- *desc = (void *) (pages + npages);3131-3232- return pages;3333-}34213522static int fuse_send_open(struct fuse_mount *fm, u64 nodeid, struct file *file,3623 int opcode, struct fuse_open_out *outargp)···13331346 return written ? written : err;13341347}1335134813361336-static inline void fuse_page_descs_length_init(struct fuse_page_desc *descs,13371337- unsigned int index,13381338- unsigned int nr_pages)13391339-{13401340- int i;13411341-13421342- for (i = index; i < index + nr_pages; i++)13431343- descs[i].length = PAGE_SIZE - descs[i].offset;13441344-}13451345-13461349static inline unsigned long fuse_get_user_addr(const struct iov_iter *ii)13471350{13481351 return (unsigned long)ii->iov->iov_base + ii->iov_offset;···26112634 }2612263526132636 return retval;26142614-}26152615-26162616-/*26172617- * CUSE servers compiled on 32bit broke on 64bit kernels because the26182618- * ABI was defined to be 'struct iovec' which is different on 32bit26192619- * and 64bit. Fortunately we can determine which structure the server26202620- * used from the size of the reply.26212621- */26222622-static int fuse_copy_ioctl_iovec_old(struct iovec *dst, void *src,26232623- size_t transferred, unsigned count,26242624- bool is_compat)26252625-{26262626-#ifdef CONFIG_COMPAT26272627- if (count * sizeof(struct compat_iovec) == transferred) {26282628- struct compat_iovec *ciov = src;26292629- unsigned i;26302630-26312631- /*26322632- * With this interface a 32bit server cannot support26332633- * non-compat (i.e. ones coming from 64bit apps) ioctl26342634- * requests26352635- */26362636- if (!is_compat)26372637- return -EINVAL;26382638-26392639- for (i = 0; i < count; i++) {26402640- dst[i].iov_base = compat_ptr(ciov[i].iov_base);26412641- dst[i].iov_len = ciov[i].iov_len;26422642- }26432643- return 0;26442644- }26452645-#endif26462646-26472647- if (count * sizeof(struct iovec) != transferred)26482648- return -EIO;26492649-26502650- memcpy(dst, src, transferred);26512651- return 0;26522652-}26532653-26542654-/* Make sure iov_length() won't overflow */26552655-static int fuse_verify_ioctl_iov(struct fuse_conn *fc, struct iovec *iov,26562656- size_t count)26572657-{26582658- size_t n;26592659- u32 max = fc->max_pages << PAGE_SHIFT;26602660-26612661- for (n = 0; n < count; n++, iov++) {26622662- if (iov->iov_len > (size_t) max)26632663- return -ENOMEM;26642664- max -= iov->iov_len;26652665- }26662666- return 0;26672667-}26682668-26692669-static int fuse_copy_ioctl_iovec(struct fuse_conn *fc, struct iovec *dst,26702670- void *src, size_t transferred, unsigned count,26712671- bool is_compat)26722672-{26732673- unsigned i;26742674- struct fuse_ioctl_iovec *fiov = src;26752675-26762676- if (fc->minor < 16) {26772677- return fuse_copy_ioctl_iovec_old(dst, src, transferred,26782678- count, is_compat);26792679- }26802680-26812681- if (count * sizeof(struct fuse_ioctl_iovec) != transferred)26822682- return -EIO;26832683-26842684- for (i = 0; i < count; i++) {26852685- /* Did the server supply an inappropriate value? */26862686- if (fiov[i].base != (unsigned long) fiov[i].base ||26872687- fiov[i].len != (unsigned long) fiov[i].len)26882688- return -EIO;26892689-26902690- dst[i].iov_base = (void __user *) (unsigned long) fiov[i].base;26912691- dst[i].iov_len = (size_t) fiov[i].len;26922692-26932693-#ifdef CONFIG_COMPAT26942694- if (is_compat &&26952695- (ptr_to_compat(dst[i].iov_base) != fiov[i].base ||26962696- (compat_size_t) dst[i].iov_len != fiov[i].len))26972697- return -EIO;26982698-#endif26992699- }27002700-27012701- return 0;27022702-}27032703-27042704-27052705-/*27062706- * For ioctls, there is no generic way to determine how much memory27072707- * needs to be read and/or written. Furthermore, ioctls are allowed27082708- * to dereference the passed pointer, so the parameter requires deep27092709- * copying but FUSE has no idea whatsoever about what to copy in or27102710- * out.27112711- *27122712- * This is solved by allowing FUSE server to retry ioctl with27132713- * necessary in/out iovecs. Let's assume the ioctl implementation27142714- * needs to read in the following structure.27152715- *27162716- * struct a {27172717- * char *buf;27182718- * size_t buflen;27192719- * }27202720- *27212721- * On the first callout to FUSE server, inarg->in_size and27222722- * inarg->out_size will be NULL; then, the server completes the ioctl27232723- * with FUSE_IOCTL_RETRY set in out->flags, out->in_iovs set to 1 and27242724- * the actual iov array to27252725- *27262726- * { { .iov_base = inarg.arg, .iov_len = sizeof(struct a) } }27272727- *27282728- * which tells FUSE to copy in the requested area and retry the ioctl.27292729- * On the second round, the server has access to the structure and27302730- * from that it can tell what to look for next, so on the invocation,27312731- * it sets FUSE_IOCTL_RETRY, out->in_iovs to 2 and iov array to27322732- *27332733- * { { .iov_base = inarg.arg, .iov_len = sizeof(struct a) },27342734- * { .iov_base = a.buf, .iov_len = a.buflen } }27352735- *27362736- * FUSE will copy both struct a and the pointed buffer from the27372737- * process doing the ioctl and retry ioctl with both struct a and the27382738- * buffer.27392739- *27402740- * This time, FUSE server has everything it needs and completes ioctl27412741- * without FUSE_IOCTL_RETRY which finishes the ioctl call.27422742- *27432743- * Copying data out works the same way.27442744- *27452745- * Note that if FUSE_IOCTL_UNRESTRICTED is clear, the kernel27462746- * automatically initializes in and out iovs by decoding @cmd with27472747- * _IOC_* macros and the server is not allowed to request RETRY. This27482748- * limits ioctl data transfers to well-formed ioctls and is the forced27492749- * behavior for all FUSE servers.27502750- */27512751-long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg,27522752- unsigned int flags)27532753-{27542754- struct fuse_file *ff = file->private_data;27552755- struct fuse_mount *fm = ff->fm;27562756- struct fuse_ioctl_in inarg = {27572757- .fh = ff->fh,27582758- .cmd = cmd,27592759- .arg = arg,27602760- .flags = flags27612761- };27622762- struct fuse_ioctl_out outarg;27632763- struct iovec *iov_page = NULL;27642764- struct iovec *in_iov = NULL, *out_iov = NULL;27652765- unsigned int in_iovs = 0, out_iovs = 0, max_pages;27662766- size_t in_size, out_size, c;27672767- ssize_t transferred;27682768- int err, i;27692769- struct iov_iter ii;27702770- struct fuse_args_pages ap = {};27712771-27722772-#if BITS_PER_LONG == 3227732773- inarg.flags |= FUSE_IOCTL_32BIT;27742774-#else27752775- if (flags & FUSE_IOCTL_COMPAT) {27762776- inarg.flags |= FUSE_IOCTL_32BIT;27772777-#ifdef CONFIG_X86_X3227782778- if (in_x32_syscall())27792779- inarg.flags |= FUSE_IOCTL_COMPAT_X32;27802780-#endif27812781- }27822782-#endif27832783-27842784- /* assume all the iovs returned by client always fits in a page */27852785- BUILD_BUG_ON(sizeof(struct fuse_ioctl_iovec) * FUSE_IOCTL_MAX_IOV > PAGE_SIZE);27862786-27872787- err = -ENOMEM;27882788- ap.pages = fuse_pages_alloc(fm->fc->max_pages, GFP_KERNEL, &ap.descs);27892789- iov_page = (struct iovec *) __get_free_page(GFP_KERNEL);27902790- if (!ap.pages || !iov_page)27912791- goto out;27922792-27932793- fuse_page_descs_length_init(ap.descs, 0, fm->fc->max_pages);27942794-27952795- /*27962796- * If restricted, initialize IO parameters as encoded in @cmd.27972797- * RETRY from server is not allowed.27982798- */27992799- if (!(flags & FUSE_IOCTL_UNRESTRICTED)) {28002800- struct iovec *iov = iov_page;28012801-28022802- iov->iov_base = (void __user *)arg;28032803-28042804- switch (cmd) {28052805- case FS_IOC_GETFLAGS:28062806- case FS_IOC_SETFLAGS:28072807- iov->iov_len = sizeof(int);28082808- break;28092809- default:28102810- iov->iov_len = _IOC_SIZE(cmd);28112811- break;28122812- }28132813-28142814- if (_IOC_DIR(cmd) & _IOC_WRITE) {28152815- in_iov = iov;28162816- in_iovs = 1;28172817- }28182818-28192819- if (_IOC_DIR(cmd) & _IOC_READ) {28202820- out_iov = iov;28212821- out_iovs = 1;28222822- }28232823- }28242824-28252825- retry:28262826- inarg.in_size = in_size = iov_length(in_iov, in_iovs);28272827- inarg.out_size = out_size = iov_length(out_iov, out_iovs);28282828-28292829- /*28302830- * Out data can be used either for actual out data or iovs,28312831- * make sure there always is at least one page.28322832- */28332833- out_size = max_t(size_t, out_size, PAGE_SIZE);28342834- max_pages = DIV_ROUND_UP(max(in_size, out_size), PAGE_SIZE);28352835-28362836- /* make sure there are enough buffer pages and init request with them */28372837- err = -ENOMEM;28382838- if (max_pages > fm->fc->max_pages)28392839- goto out;28402840- while (ap.num_pages < max_pages) {28412841- ap.pages[ap.num_pages] = alloc_page(GFP_KERNEL | __GFP_HIGHMEM);28422842- if (!ap.pages[ap.num_pages])28432843- goto out;28442844- ap.num_pages++;28452845- }28462846-28472847-28482848- /* okay, let's send it to the client */28492849- ap.args.opcode = FUSE_IOCTL;28502850- ap.args.nodeid = ff->nodeid;28512851- ap.args.in_numargs = 1;28522852- ap.args.in_args[0].size = sizeof(inarg);28532853- ap.args.in_args[0].value = &inarg;28542854- if (in_size) {28552855- ap.args.in_numargs++;28562856- ap.args.in_args[1].size = in_size;28572857- ap.args.in_pages = true;28582858-28592859- err = -EFAULT;28602860- iov_iter_init(&ii, WRITE, in_iov, in_iovs, in_size);28612861- for (i = 0; iov_iter_count(&ii) && !WARN_ON(i >= ap.num_pages); i++) {28622862- c = copy_page_from_iter(ap.pages[i], 0, PAGE_SIZE, &ii);28632863- if (c != PAGE_SIZE && iov_iter_count(&ii))28642864- goto out;28652865- }28662866- }28672867-28682868- ap.args.out_numargs = 2;28692869- ap.args.out_args[0].size = sizeof(outarg);28702870- ap.args.out_args[0].value = &outarg;28712871- ap.args.out_args[1].size = out_size;28722872- ap.args.out_pages = true;28732873- ap.args.out_argvar = true;28742874-28752875- transferred = fuse_simple_request(fm, &ap.args);28762876- err = transferred;28772877- if (transferred < 0)28782878- goto out;28792879-28802880- /* did it ask for retry? */28812881- if (outarg.flags & FUSE_IOCTL_RETRY) {28822882- void *vaddr;28832883-28842884- /* no retry if in restricted mode */28852885- err = -EIO;28862886- if (!(flags & FUSE_IOCTL_UNRESTRICTED))28872887- goto out;28882888-28892889- in_iovs = outarg.in_iovs;28902890- out_iovs = outarg.out_iovs;28912891-28922892- /*28932893- * Make sure things are in boundary, separate checks28942894- * are to protect against overflow.28952895- */28962896- err = -ENOMEM;28972897- if (in_iovs > FUSE_IOCTL_MAX_IOV ||28982898- out_iovs > FUSE_IOCTL_MAX_IOV ||28992899- in_iovs + out_iovs > FUSE_IOCTL_MAX_IOV)29002900- goto out;29012901-29022902- vaddr = kmap_atomic(ap.pages[0]);29032903- err = fuse_copy_ioctl_iovec(fm->fc, iov_page, vaddr,29042904- transferred, in_iovs + out_iovs,29052905- (flags & FUSE_IOCTL_COMPAT) != 0);29062906- kunmap_atomic(vaddr);29072907- if (err)29082908- goto out;29092909-29102910- in_iov = iov_page;29112911- out_iov = in_iov + in_iovs;29122912-29132913- err = fuse_verify_ioctl_iov(fm->fc, in_iov, in_iovs);29142914- if (err)29152915- goto out;29162916-29172917- err = fuse_verify_ioctl_iov(fm->fc, out_iov, out_iovs);29182918- if (err)29192919- goto out;29202920-29212921- goto retry;29222922- }29232923-29242924- err = -EIO;29252925- if (transferred > inarg.out_size)29262926- goto out;29272927-29282928- err = -EFAULT;29292929- iov_iter_init(&ii, READ, out_iov, out_iovs, transferred);29302930- for (i = 0; iov_iter_count(&ii) && !WARN_ON(i >= ap.num_pages); i++) {29312931- c = copy_page_to_iter(ap.pages[i], 0, PAGE_SIZE, &ii);29322932- if (c != PAGE_SIZE && iov_iter_count(&ii))29332933- goto out;29342934- }29352935- err = 0;29362936- out:29372937- free_page((unsigned long) iov_page);29382938- while (ap.num_pages)29392939- __free_page(ap.pages[--ap.num_pages]);29402940- kfree(ap.pages);29412941-29422942- return err ? err : outarg.result;29432943-}29442944-EXPORT_SYMBOL_GPL(fuse_do_ioctl);29452945-29462946-long fuse_ioctl_common(struct file *file, unsigned int cmd,29472947- unsigned long arg, unsigned int flags)29482948-{29492949- struct inode *inode = file_inode(file);29502950- struct fuse_conn *fc = get_fuse_conn(inode);29512951-29522952- if (!fuse_allow_current_process(fc))29532953- return -EACCES;29542954-29552955- if (fuse_is_bad(inode))29562956- return -EIO;29572957-29582958- return fuse_do_ioctl(file, cmd, arg, flags);29592959-}29602960-29612961-static long fuse_file_ioctl(struct file *file, unsigned int cmd,29622962- unsigned long arg)29632963-{29642964- return fuse_ioctl_common(file, cmd, arg, 0);29652965-}29662966-29672967-static long fuse_file_compat_ioctl(struct file *file, unsigned int cmd,29682968- unsigned long arg)29692969-{29702970- return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_COMPAT);29712637}2972263829732639/*
+27
fs/fuse/fuse_i.h
···872872 return unlikely(test_bit(FUSE_I_BAD, &get_fuse_inode(inode)->state));873873}874874875875+static inline struct page **fuse_pages_alloc(unsigned int npages, gfp_t flags,876876+ struct fuse_page_desc **desc)877877+{878878+ struct page **pages;879879+880880+ pages = kzalloc(npages * (sizeof(struct page *) +881881+ sizeof(struct fuse_page_desc)), flags);882882+ *desc = (void *) (pages + npages);883883+884884+ return pages;885885+}886886+887887+static inline void fuse_page_descs_length_init(struct fuse_page_desc *descs,888888+ unsigned int index,889889+ unsigned int nr_pages)890890+{891891+ int i;892892+893893+ for (i = index; i < index + nr_pages; i++)894894+ descs[i].length = PAGE_SIZE - descs[i].offset;895895+}896896+875897/** Device operations */876898extern const struct file_operations fuse_dev_operations;877899···12351213void fuse_dax_inode_cleanup(struct inode *inode);12361214bool fuse_dax_check_alignment(struct fuse_conn *fc, unsigned int map_alignment);12371215void fuse_dax_cancel_work(struct fuse_conn *fc);12161216+12171217+/* ioctl.c */12181218+long fuse_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg);12191219+long fuse_file_compat_ioctl(struct file *file, unsigned int cmd,12201220+ unsigned long arg);1238122112391222#endif /* _FS_FUSE_I_H */
+366
fs/fuse/ioctl.c
···11+// SPDX-License-Identifier: GPL-2.0-only22+/*33+ * Copyright (C) 2017 Red Hat, Inc.44+ */55+66+#include "fuse_i.h"77+88+#include <linux/uio.h>99+#include <linux/compat.h>1010+#include <linux/fileattr.h>1111+1212+/*1313+ * CUSE servers compiled on 32bit broke on 64bit kernels because the1414+ * ABI was defined to be 'struct iovec' which is different on 32bit1515+ * and 64bit. Fortunately we can determine which structure the server1616+ * used from the size of the reply.1717+ */1818+static int fuse_copy_ioctl_iovec_old(struct iovec *dst, void *src,1919+ size_t transferred, unsigned count,2020+ bool is_compat)2121+{2222+#ifdef CONFIG_COMPAT2323+ if (count * sizeof(struct compat_iovec) == transferred) {2424+ struct compat_iovec *ciov = src;2525+ unsigned i;2626+2727+ /*2828+ * With this interface a 32bit server cannot support2929+ * non-compat (i.e. ones coming from 64bit apps) ioctl3030+ * requests3131+ */3232+ if (!is_compat)3333+ return -EINVAL;3434+3535+ for (i = 0; i < count; i++) {3636+ dst[i].iov_base = compat_ptr(ciov[i].iov_base);3737+ dst[i].iov_len = ciov[i].iov_len;3838+ }3939+ return 0;4040+ }4141+#endif4242+4343+ if (count * sizeof(struct iovec) != transferred)4444+ return -EIO;4545+4646+ memcpy(dst, src, transferred);4747+ return 0;4848+}4949+5050+/* Make sure iov_length() won't overflow */5151+static int fuse_verify_ioctl_iov(struct fuse_conn *fc, struct iovec *iov,5252+ size_t count)5353+{5454+ size_t n;5555+ u32 max = fc->max_pages << PAGE_SHIFT;5656+5757+ for (n = 0; n < count; n++, iov++) {5858+ if (iov->iov_len > (size_t) max)5959+ return -ENOMEM;6060+ max -= iov->iov_len;6161+ }6262+ return 0;6363+}6464+6565+static int fuse_copy_ioctl_iovec(struct fuse_conn *fc, struct iovec *dst,6666+ void *src, size_t transferred, unsigned count,6767+ bool is_compat)6868+{6969+ unsigned i;7070+ struct fuse_ioctl_iovec *fiov = src;7171+7272+ if (fc->minor < 16) {7373+ return fuse_copy_ioctl_iovec_old(dst, src, transferred,7474+ count, is_compat);7575+ }7676+7777+ if (count * sizeof(struct fuse_ioctl_iovec) != transferred)7878+ return -EIO;7979+8080+ for (i = 0; i < count; i++) {8181+ /* Did the server supply an inappropriate value? */8282+ if (fiov[i].base != (unsigned long) fiov[i].base ||8383+ fiov[i].len != (unsigned long) fiov[i].len)8484+ return -EIO;8585+8686+ dst[i].iov_base = (void __user *) (unsigned long) fiov[i].base;8787+ dst[i].iov_len = (size_t) fiov[i].len;8888+8989+#ifdef CONFIG_COMPAT9090+ if (is_compat &&9191+ (ptr_to_compat(dst[i].iov_base) != fiov[i].base ||9292+ (compat_size_t) dst[i].iov_len != fiov[i].len))9393+ return -EIO;9494+#endif9595+ }9696+9797+ return 0;9898+}9999+100100+101101+/*102102+ * For ioctls, there is no generic way to determine how much memory103103+ * needs to be read and/or written. Furthermore, ioctls are allowed104104+ * to dereference the passed pointer, so the parameter requires deep105105+ * copying but FUSE has no idea whatsoever about what to copy in or106106+ * out.107107+ *108108+ * This is solved by allowing FUSE server to retry ioctl with109109+ * necessary in/out iovecs. Let's assume the ioctl implementation110110+ * needs to read in the following structure.111111+ *112112+ * struct a {113113+ * char *buf;114114+ * size_t buflen;115115+ * }116116+ *117117+ * On the first callout to FUSE server, inarg->in_size and118118+ * inarg->out_size will be NULL; then, the server completes the ioctl119119+ * with FUSE_IOCTL_RETRY set in out->flags, out->in_iovs set to 1 and120120+ * the actual iov array to121121+ *122122+ * { { .iov_base = inarg.arg, .iov_len = sizeof(struct a) } }123123+ *124124+ * which tells FUSE to copy in the requested area and retry the ioctl.125125+ * On the second round, the server has access to the structure and126126+ * from that it can tell what to look for next, so on the invocation,127127+ * it sets FUSE_IOCTL_RETRY, out->in_iovs to 2 and iov array to128128+ *129129+ * { { .iov_base = inarg.arg, .iov_len = sizeof(struct a) },130130+ * { .iov_base = a.buf, .iov_len = a.buflen } }131131+ *132132+ * FUSE will copy both struct a and the pointed buffer from the133133+ * process doing the ioctl and retry ioctl with both struct a and the134134+ * buffer.135135+ *136136+ * This time, FUSE server has everything it needs and completes ioctl137137+ * without FUSE_IOCTL_RETRY which finishes the ioctl call.138138+ *139139+ * Copying data out works the same way.140140+ *141141+ * Note that if FUSE_IOCTL_UNRESTRICTED is clear, the kernel142142+ * automatically initializes in and out iovs by decoding @cmd with143143+ * _IOC_* macros and the server is not allowed to request RETRY. This144144+ * limits ioctl data transfers to well-formed ioctls and is the forced145145+ * behavior for all FUSE servers.146146+ */147147+long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg,148148+ unsigned int flags)149149+{150150+ struct fuse_file *ff = file->private_data;151151+ struct fuse_mount *fm = ff->fm;152152+ struct fuse_ioctl_in inarg = {153153+ .fh = ff->fh,154154+ .cmd = cmd,155155+ .arg = arg,156156+ .flags = flags157157+ };158158+ struct fuse_ioctl_out outarg;159159+ struct iovec *iov_page = NULL;160160+ struct iovec *in_iov = NULL, *out_iov = NULL;161161+ unsigned int in_iovs = 0, out_iovs = 0, max_pages;162162+ size_t in_size, out_size, c;163163+ ssize_t transferred;164164+ int err, i;165165+ struct iov_iter ii;166166+ struct fuse_args_pages ap = {};167167+168168+#if BITS_PER_LONG == 32169169+ inarg.flags |= FUSE_IOCTL_32BIT;170170+#else171171+ if (flags & FUSE_IOCTL_COMPAT) {172172+ inarg.flags |= FUSE_IOCTL_32BIT;173173+#ifdef CONFIG_X86_X32174174+ if (in_x32_syscall())175175+ inarg.flags |= FUSE_IOCTL_COMPAT_X32;176176+#endif177177+ }178178+#endif179179+180180+ /* assume all the iovs returned by client always fits in a page */181181+ BUILD_BUG_ON(sizeof(struct fuse_ioctl_iovec) * FUSE_IOCTL_MAX_IOV > PAGE_SIZE);182182+183183+ err = -ENOMEM;184184+ ap.pages = fuse_pages_alloc(fm->fc->max_pages, GFP_KERNEL, &ap.descs);185185+ iov_page = (struct iovec *) __get_free_page(GFP_KERNEL);186186+ if (!ap.pages || !iov_page)187187+ goto out;188188+189189+ fuse_page_descs_length_init(ap.descs, 0, fm->fc->max_pages);190190+191191+ /*192192+ * If restricted, initialize IO parameters as encoded in @cmd.193193+ * RETRY from server is not allowed.194194+ */195195+ if (!(flags & FUSE_IOCTL_UNRESTRICTED)) {196196+ struct iovec *iov = iov_page;197197+198198+ iov->iov_base = (void __user *)arg;199199+200200+ switch (cmd) {201201+ case FS_IOC_GETFLAGS:202202+ case FS_IOC_SETFLAGS:203203+ iov->iov_len = sizeof(int);204204+ break;205205+ default:206206+ iov->iov_len = _IOC_SIZE(cmd);207207+ break;208208+ }209209+210210+ if (_IOC_DIR(cmd) & _IOC_WRITE) {211211+ in_iov = iov;212212+ in_iovs = 1;213213+ }214214+215215+ if (_IOC_DIR(cmd) & _IOC_READ) {216216+ out_iov = iov;217217+ out_iovs = 1;218218+ }219219+ }220220+221221+ retry:222222+ inarg.in_size = in_size = iov_length(in_iov, in_iovs);223223+ inarg.out_size = out_size = iov_length(out_iov, out_iovs);224224+225225+ /*226226+ * Out data can be used either for actual out data or iovs,227227+ * make sure there always is at least one page.228228+ */229229+ out_size = max_t(size_t, out_size, PAGE_SIZE);230230+ max_pages = DIV_ROUND_UP(max(in_size, out_size), PAGE_SIZE);231231+232232+ /* make sure there are enough buffer pages and init request with them */233233+ err = -ENOMEM;234234+ if (max_pages > fm->fc->max_pages)235235+ goto out;236236+ while (ap.num_pages < max_pages) {237237+ ap.pages[ap.num_pages] = alloc_page(GFP_KERNEL | __GFP_HIGHMEM);238238+ if (!ap.pages[ap.num_pages])239239+ goto out;240240+ ap.num_pages++;241241+ }242242+243243+244244+ /* okay, let's send it to the client */245245+ ap.args.opcode = FUSE_IOCTL;246246+ ap.args.nodeid = ff->nodeid;247247+ ap.args.in_numargs = 1;248248+ ap.args.in_args[0].size = sizeof(inarg);249249+ ap.args.in_args[0].value = &inarg;250250+ if (in_size) {251251+ ap.args.in_numargs++;252252+ ap.args.in_args[1].size = in_size;253253+ ap.args.in_pages = true;254254+255255+ err = -EFAULT;256256+ iov_iter_init(&ii, WRITE, in_iov, in_iovs, in_size);257257+ for (i = 0; iov_iter_count(&ii) && !WARN_ON(i >= ap.num_pages); i++) {258258+ c = copy_page_from_iter(ap.pages[i], 0, PAGE_SIZE, &ii);259259+ if (c != PAGE_SIZE && iov_iter_count(&ii))260260+ goto out;261261+ }262262+ }263263+264264+ ap.args.out_numargs = 2;265265+ ap.args.out_args[0].size = sizeof(outarg);266266+ ap.args.out_args[0].value = &outarg;267267+ ap.args.out_args[1].size = out_size;268268+ ap.args.out_pages = true;269269+ ap.args.out_argvar = true;270270+271271+ transferred = fuse_simple_request(fm, &ap.args);272272+ err = transferred;273273+ if (transferred < 0)274274+ goto out;275275+276276+ /* did it ask for retry? */277277+ if (outarg.flags & FUSE_IOCTL_RETRY) {278278+ void *vaddr;279279+280280+ /* no retry if in restricted mode */281281+ err = -EIO;282282+ if (!(flags & FUSE_IOCTL_UNRESTRICTED))283283+ goto out;284284+285285+ in_iovs = outarg.in_iovs;286286+ out_iovs = outarg.out_iovs;287287+288288+ /*289289+ * Make sure things are in boundary, separate checks290290+ * are to protect against overflow.291291+ */292292+ err = -ENOMEM;293293+ if (in_iovs > FUSE_IOCTL_MAX_IOV ||294294+ out_iovs > FUSE_IOCTL_MAX_IOV ||295295+ in_iovs + out_iovs > FUSE_IOCTL_MAX_IOV)296296+ goto out;297297+298298+ vaddr = kmap_atomic(ap.pages[0]);299299+ err = fuse_copy_ioctl_iovec(fm->fc, iov_page, vaddr,300300+ transferred, in_iovs + out_iovs,301301+ (flags & FUSE_IOCTL_COMPAT) != 0);302302+ kunmap_atomic(vaddr);303303+ if (err)304304+ goto out;305305+306306+ in_iov = iov_page;307307+ out_iov = in_iov + in_iovs;308308+309309+ err = fuse_verify_ioctl_iov(fm->fc, in_iov, in_iovs);310310+ if (err)311311+ goto out;312312+313313+ err = fuse_verify_ioctl_iov(fm->fc, out_iov, out_iovs);314314+ if (err)315315+ goto out;316316+317317+ goto retry;318318+ }319319+320320+ err = -EIO;321321+ if (transferred > inarg.out_size)322322+ goto out;323323+324324+ err = -EFAULT;325325+ iov_iter_init(&ii, READ, out_iov, out_iovs, transferred);326326+ for (i = 0; iov_iter_count(&ii) && !WARN_ON(i >= ap.num_pages); i++) {327327+ c = copy_page_to_iter(ap.pages[i], 0, PAGE_SIZE, &ii);328328+ if (c != PAGE_SIZE && iov_iter_count(&ii))329329+ goto out;330330+ }331331+ err = 0;332332+ out:333333+ free_page((unsigned long) iov_page);334334+ while (ap.num_pages)335335+ __free_page(ap.pages[--ap.num_pages]);336336+ kfree(ap.pages);337337+338338+ return err ? err : outarg.result;339339+}340340+EXPORT_SYMBOL_GPL(fuse_do_ioctl);341341+342342+long fuse_ioctl_common(struct file *file, unsigned int cmd,343343+ unsigned long arg, unsigned int flags)344344+{345345+ struct inode *inode = file_inode(file);346346+ struct fuse_conn *fc = get_fuse_conn(inode);347347+348348+ if (!fuse_allow_current_process(fc))349349+ return -EACCES;350350+351351+ if (fuse_is_bad(inode))352352+ return -EIO;353353+354354+ return fuse_do_ioctl(file, cmd, arg, flags);355355+}356356+357357+long fuse_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)358358+{359359+ return fuse_ioctl_common(file, cmd, arg, 0);360360+}361361+362362+long fuse_file_compat_ioctl(struct file *file, unsigned int cmd,363363+ unsigned long arg)364364+{365365+ return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_COMPAT);366366+}