statfs.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. #include <linux/syscalls.h>
  2. #include <linux/module.h>
  3. #include <linux/fs.h>
  4. #include <linux/file.h>
  5. #include <linux/mount.h>
  6. #include <linux/namei.h>
  7. #include <linux/statfs.h>
  8. #include <linux/security.h>
  9. #include <linux/uaccess.h>
  10. static int flags_by_mnt(int mnt_flags)
  11. {
  12. int flags = 0;
  13. if (mnt_flags & MNT_READONLY)
  14. flags |= ST_RDONLY;
  15. if (mnt_flags & MNT_NOSUID)
  16. flags |= ST_NOSUID;
  17. if (mnt_flags & MNT_NODEV)
  18. flags |= ST_NODEV;
  19. if (mnt_flags & MNT_NOEXEC)
  20. flags |= ST_NOEXEC;
  21. if (mnt_flags & MNT_NOATIME)
  22. flags |= ST_NOATIME;
  23. if (mnt_flags & MNT_NODIRATIME)
  24. flags |= ST_NODIRATIME;
  25. if (mnt_flags & MNT_RELATIME)
  26. flags |= ST_RELATIME;
  27. return flags;
  28. }
  29. static int flags_by_sb(int s_flags)
  30. {
  31. int flags = 0;
  32. if (s_flags & MS_SYNCHRONOUS)
  33. flags |= ST_SYNCHRONOUS;
  34. if (s_flags & MS_MANDLOCK)
  35. flags |= ST_MANDLOCK;
  36. return flags;
  37. }
  38. static int calculate_f_flags(struct vfsmount *mnt)
  39. {
  40. return ST_VALID | flags_by_mnt(mnt->mnt_flags) |
  41. flags_by_sb(mnt->mnt_sb->s_flags);
  42. }
  43. int statfs_by_dentry(struct dentry *dentry, struct kstatfs *buf)
  44. {
  45. int retval;
  46. if (!dentry->d_sb->s_op->statfs)
  47. return -ENOSYS;
  48. memset(buf, 0, sizeof(*buf));
  49. retval = security_sb_statfs(dentry);
  50. if (retval)
  51. return retval;
  52. retval = dentry->d_sb->s_op->statfs(dentry, buf);
  53. if (retval == 0 && buf->f_frsize == 0)
  54. buf->f_frsize = buf->f_bsize;
  55. return retval;
  56. }
  57. int vfs_statfs(struct path *path, struct kstatfs *buf)
  58. {
  59. int error;
  60. error = statfs_by_dentry(path->dentry, buf);
  61. if (!error)
  62. buf->f_flags = calculate_f_flags(path->mnt);
  63. return error;
  64. }
  65. EXPORT_SYMBOL(vfs_statfs);
  66. static int do_statfs_native(struct path *path, struct statfs *buf)
  67. {
  68. struct kstatfs st;
  69. int retval;
  70. retval = vfs_statfs(path, &st);
  71. if (retval)
  72. return retval;
  73. if (sizeof(*buf) == sizeof(st))
  74. memcpy(buf, &st, sizeof(st));
  75. else {
  76. if (sizeof buf->f_blocks == 4) {
  77. if ((st.f_blocks | st.f_bfree | st.f_bavail |
  78. st.f_bsize | st.f_frsize) &
  79. 0xffffffff00000000ULL)
  80. return -EOVERFLOW;
  81. /*
  82. * f_files and f_ffree may be -1; it's okay to stuff
  83. * that into 32 bits
  84. */
  85. if (st.f_files != -1 &&
  86. (st.f_files & 0xffffffff00000000ULL))
  87. return -EOVERFLOW;
  88. if (st.f_ffree != -1 &&
  89. (st.f_ffree & 0xffffffff00000000ULL))
  90. return -EOVERFLOW;
  91. }
  92. buf->f_type = st.f_type;
  93. buf->f_bsize = st.f_bsize;
  94. buf->f_blocks = st.f_blocks;
  95. buf->f_bfree = st.f_bfree;
  96. buf->f_bavail = st.f_bavail;
  97. buf->f_files = st.f_files;
  98. buf->f_ffree = st.f_ffree;
  99. buf->f_fsid = st.f_fsid;
  100. buf->f_namelen = st.f_namelen;
  101. buf->f_frsize = st.f_frsize;
  102. buf->f_flags = st.f_flags;
  103. memset(buf->f_spare, 0, sizeof(buf->f_spare));
  104. }
  105. return 0;
  106. }
  107. static int do_statfs64(struct path *path, struct statfs64 *buf)
  108. {
  109. struct kstatfs st;
  110. int retval;
  111. retval = vfs_statfs(path, &st);
  112. if (retval)
  113. return retval;
  114. if (sizeof(*buf) == sizeof(st))
  115. memcpy(buf, &st, sizeof(st));
  116. else {
  117. buf->f_type = st.f_type;
  118. buf->f_bsize = st.f_bsize;
  119. buf->f_blocks = st.f_blocks;
  120. buf->f_bfree = st.f_bfree;
  121. buf->f_bavail = st.f_bavail;
  122. buf->f_files = st.f_files;
  123. buf->f_ffree = st.f_ffree;
  124. buf->f_fsid = st.f_fsid;
  125. buf->f_namelen = st.f_namelen;
  126. buf->f_frsize = st.f_frsize;
  127. buf->f_flags = st.f_flags;
  128. memset(buf->f_spare, 0, sizeof(buf->f_spare));
  129. }
  130. return 0;
  131. }
  132. SYSCALL_DEFINE2(statfs, const char __user *, pathname, struct statfs __user *, buf)
  133. {
  134. struct path path;
  135. int error;
  136. error = user_path(pathname, &path);
  137. if (!error) {
  138. struct statfs tmp;
  139. error = do_statfs_native(&path, &tmp);
  140. if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
  141. error = -EFAULT;
  142. path_put(&path);
  143. }
  144. return error;
  145. }
  146. SYSCALL_DEFINE3(statfs64, const char __user *, pathname, size_t, sz, struct statfs64 __user *, buf)
  147. {
  148. struct path path;
  149. long error;
  150. if (sz != sizeof(*buf))
  151. return -EINVAL;
  152. error = user_path(pathname, &path);
  153. if (!error) {
  154. struct statfs64 tmp;
  155. error = do_statfs64(&path, &tmp);
  156. if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
  157. error = -EFAULT;
  158. path_put(&path);
  159. }
  160. return error;
  161. }
  162. SYSCALL_DEFINE2(fstatfs, unsigned int, fd, struct statfs __user *, buf)
  163. {
  164. struct file *file;
  165. struct statfs tmp;
  166. int error;
  167. error = -EBADF;
  168. file = fget(fd);
  169. if (!file)
  170. goto out;
  171. error = do_statfs_native(&file->f_path, &tmp);
  172. if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
  173. error = -EFAULT;
  174. fput(file);
  175. out:
  176. return error;
  177. }
  178. SYSCALL_DEFINE3(fstatfs64, unsigned int, fd, size_t, sz, struct statfs64 __user *, buf)
  179. {
  180. struct file *file;
  181. struct statfs64 tmp;
  182. int error;
  183. if (sz != sizeof(*buf))
  184. return -EINVAL;
  185. error = -EBADF;
  186. file = fget(fd);
  187. if (!file)
  188. goto out;
  189. error = do_statfs64(&file->f_path, &tmp);
  190. if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
  191. error = -EFAULT;
  192. fput(file);
  193. out:
  194. return error;
  195. }
  196. SYSCALL_DEFINE2(ustat, unsigned, dev, struct ustat __user *, ubuf)
  197. {
  198. struct super_block *s;
  199. struct ustat tmp;
  200. struct kstatfs sbuf;
  201. int err;
  202. s = user_get_super(new_decode_dev(dev));
  203. if (!s)
  204. return -EINVAL;
  205. err = statfs_by_dentry(s->s_root, &sbuf);
  206. drop_super(s);
  207. if (err)
  208. return err;
  209. memset(&tmp,0,sizeof(struct ustat));
  210. tmp.f_tfree = sbuf.f_bfree;
  211. tmp.f_tinode = sbuf.f_ffree;
  212. return copy_to_user(ubuf, &tmp, sizeof(struct ustat)) ? -EFAULT : 0;
  213. }