diff options
Diffstat (limited to 'fs/compat.c')
-rw-r--r-- | fs/compat.c | 63 |
1 files changed, 48 insertions, 15 deletions
diff --git a/fs/compat.c b/fs/compat.c index 075d0509970d..cb36245f9fe0 100644 --- a/fs/compat.c +++ b/fs/compat.c | |||
@@ -137,6 +137,45 @@ asmlinkage long compat_sys_utimes(char __user *filename, struct compat_timeval _ | |||
137 | return compat_sys_futimesat(AT_FDCWD, filename, t); | 137 | return compat_sys_futimesat(AT_FDCWD, filename, t); |
138 | } | 138 | } |
139 | 139 | ||
140 | static int cp_compat_stat(struct kstat *stat, struct compat_stat __user *ubuf) | ||
141 | { | ||
142 | compat_ino_t ino = stat->ino; | ||
143 | typeof(ubuf->st_uid) uid = 0; | ||
144 | typeof(ubuf->st_gid) gid = 0; | ||
145 | int err; | ||
146 | |||
147 | SET_UID(uid, stat->uid); | ||
148 | SET_GID(gid, stat->gid); | ||
149 | |||
150 | if ((u64) stat->size > MAX_NON_LFS || | ||
151 | !old_valid_dev(stat->dev) || | ||
152 | !old_valid_dev(stat->rdev)) | ||
153 | return -EOVERFLOW; | ||
154 | if (sizeof(ino) < sizeof(stat->ino) && ino != stat->ino) | ||
155 | return -EOVERFLOW; | ||
156 | |||
157 | if (clear_user(ubuf, sizeof(*ubuf))) | ||
158 | return -EFAULT; | ||
159 | |||
160 | err = __put_user(old_encode_dev(stat->dev), &ubuf->st_dev); | ||
161 | err |= __put_user(ino, &ubuf->st_ino); | ||
162 | err |= __put_user(stat->mode, &ubuf->st_mode); | ||
163 | err |= __put_user(stat->nlink, &ubuf->st_nlink); | ||
164 | err |= __put_user(uid, &ubuf->st_uid); | ||
165 | err |= __put_user(gid, &ubuf->st_gid); | ||
166 | err |= __put_user(old_encode_dev(stat->rdev), &ubuf->st_rdev); | ||
167 | err |= __put_user(stat->size, &ubuf->st_size); | ||
168 | err |= __put_user(stat->atime.tv_sec, &ubuf->st_atime); | ||
169 | err |= __put_user(stat->atime.tv_nsec, &ubuf->st_atime_nsec); | ||
170 | err |= __put_user(stat->mtime.tv_sec, &ubuf->st_mtime); | ||
171 | err |= __put_user(stat->mtime.tv_nsec, &ubuf->st_mtime_nsec); | ||
172 | err |= __put_user(stat->ctime.tv_sec, &ubuf->st_ctime); | ||
173 | err |= __put_user(stat->ctime.tv_nsec, &ubuf->st_ctime_nsec); | ||
174 | err |= __put_user(stat->blksize, &ubuf->st_blksize); | ||
175 | err |= __put_user(stat->blocks, &ubuf->st_blocks); | ||
176 | return err; | ||
177 | } | ||
178 | |||
140 | asmlinkage long compat_sys_newstat(char __user * filename, | 179 | asmlinkage long compat_sys_newstat(char __user * filename, |
141 | struct compat_stat __user *statbuf) | 180 | struct compat_stat __user *statbuf) |
142 | { | 181 | { |
@@ -830,7 +869,7 @@ asmlinkage long compat_sys_old_readdir(unsigned int fd, | |||
830 | buf.dirent = dirent; | 869 | buf.dirent = dirent; |
831 | 870 | ||
832 | error = vfs_readdir(file, compat_fillonedir, &buf); | 871 | error = vfs_readdir(file, compat_fillonedir, &buf); |
833 | if (error >= 0) | 872 | if (buf.result) |
834 | error = buf.result; | 873 | error = buf.result; |
835 | 874 | ||
836 | fput(file); | 875 | fput(file); |
@@ -917,9 +956,8 @@ asmlinkage long compat_sys_getdents(unsigned int fd, | |||
917 | buf.error = 0; | 956 | buf.error = 0; |
918 | 957 | ||
919 | error = vfs_readdir(file, compat_filldir, &buf); | 958 | error = vfs_readdir(file, compat_filldir, &buf); |
920 | if (error < 0) | 959 | if (error >= 0) |
921 | goto out_putf; | 960 | error = buf.error; |
922 | error = buf.error; | ||
923 | lastdirent = buf.previous; | 961 | lastdirent = buf.previous; |
924 | if (lastdirent) { | 962 | if (lastdirent) { |
925 | if (put_user(file->f_pos, &lastdirent->d_off)) | 963 | if (put_user(file->f_pos, &lastdirent->d_off)) |
@@ -927,8 +965,6 @@ asmlinkage long compat_sys_getdents(unsigned int fd, | |||
927 | else | 965 | else |
928 | error = count - buf.count; | 966 | error = count - buf.count; |
929 | } | 967 | } |
930 | |||
931 | out_putf: | ||
932 | fput(file); | 968 | fput(file); |
933 | out: | 969 | out: |
934 | return error; | 970 | return error; |
@@ -1008,19 +1044,16 @@ asmlinkage long compat_sys_getdents64(unsigned int fd, | |||
1008 | buf.error = 0; | 1044 | buf.error = 0; |
1009 | 1045 | ||
1010 | error = vfs_readdir(file, compat_filldir64, &buf); | 1046 | error = vfs_readdir(file, compat_filldir64, &buf); |
1011 | if (error < 0) | 1047 | if (error >= 0) |
1012 | goto out_putf; | 1048 | error = buf.error; |
1013 | error = buf.error; | ||
1014 | lastdirent = buf.previous; | 1049 | lastdirent = buf.previous; |
1015 | if (lastdirent) { | 1050 | if (lastdirent) { |
1016 | typeof(lastdirent->d_off) d_off = file->f_pos; | 1051 | typeof(lastdirent->d_off) d_off = file->f_pos; |
1017 | error = -EFAULT; | ||
1018 | if (__put_user_unaligned(d_off, &lastdirent->d_off)) | 1052 | if (__put_user_unaligned(d_off, &lastdirent->d_off)) |
1019 | goto out_putf; | 1053 | error = -EFAULT; |
1020 | error = count - buf.count; | 1054 | else |
1055 | error = count - buf.count; | ||
1021 | } | 1056 | } |
1022 | |||
1023 | out_putf: | ||
1024 | fput(file); | 1057 | fput(file); |
1025 | out: | 1058 | out: |
1026 | return error; | 1059 | return error; |
@@ -1239,7 +1272,7 @@ static int compat_count(compat_uptr_t __user *argv, int max) | |||
1239 | if (!p) | 1272 | if (!p) |
1240 | break; | 1273 | break; |
1241 | argv++; | 1274 | argv++; |
1242 | if(++i > max) | 1275 | if (i++ >= max) |
1243 | return -E2BIG; | 1276 | return -E2BIG; |
1244 | } | 1277 | } |
1245 | } | 1278 | } |