diff options
Diffstat (limited to 'fs/compat.c')
-rw-r--r-- | fs/compat.c | 43 |
1 files changed, 22 insertions, 21 deletions
diff --git a/fs/compat.c b/fs/compat.c index fc3b55dce184..6af20de2c1a3 100644 --- a/fs/compat.c +++ b/fs/compat.c | |||
@@ -832,6 +832,7 @@ struct compat_old_linux_dirent { | |||
832 | }; | 832 | }; |
833 | 833 | ||
834 | struct compat_readdir_callback { | 834 | struct compat_readdir_callback { |
835 | struct dir_context ctx; | ||
835 | struct compat_old_linux_dirent __user *dirent; | 836 | struct compat_old_linux_dirent __user *dirent; |
836 | int result; | 837 | int result; |
837 | }; | 838 | }; |
@@ -873,15 +874,15 @@ asmlinkage long compat_sys_old_readdir(unsigned int fd, | |||
873 | { | 874 | { |
874 | int error; | 875 | int error; |
875 | struct fd f = fdget(fd); | 876 | struct fd f = fdget(fd); |
876 | struct compat_readdir_callback buf; | 877 | struct compat_readdir_callback buf = { |
878 | .ctx.actor = compat_fillonedir, | ||
879 | .dirent = dirent | ||
880 | }; | ||
877 | 881 | ||
878 | if (!f.file) | 882 | if (!f.file) |
879 | return -EBADF; | 883 | return -EBADF; |
880 | 884 | ||
881 | buf.result = 0; | 885 | error = iterate_dir(f.file, &buf.ctx); |
882 | buf.dirent = dirent; | ||
883 | |||
884 | error = vfs_readdir(f.file, compat_fillonedir, &buf); | ||
885 | if (buf.result) | 886 | if (buf.result) |
886 | error = buf.result; | 887 | error = buf.result; |
887 | 888 | ||
@@ -897,6 +898,7 @@ struct compat_linux_dirent { | |||
897 | }; | 898 | }; |
898 | 899 | ||
899 | struct compat_getdents_callback { | 900 | struct compat_getdents_callback { |
901 | struct dir_context ctx; | ||
900 | struct compat_linux_dirent __user *current_dir; | 902 | struct compat_linux_dirent __user *current_dir; |
901 | struct compat_linux_dirent __user *previous; | 903 | struct compat_linux_dirent __user *previous; |
902 | int count; | 904 | int count; |
@@ -951,7 +953,11 @@ asmlinkage long compat_sys_getdents(unsigned int fd, | |||
951 | { | 953 | { |
952 | struct fd f; | 954 | struct fd f; |
953 | struct compat_linux_dirent __user * lastdirent; | 955 | struct compat_linux_dirent __user * lastdirent; |
954 | struct compat_getdents_callback buf; | 956 | struct compat_getdents_callback buf = { |
957 | .ctx.actor = compat_filldir, | ||
958 | .current_dir = dirent, | ||
959 | .count = count | ||
960 | }; | ||
955 | int error; | 961 | int error; |
956 | 962 | ||
957 | if (!access_ok(VERIFY_WRITE, dirent, count)) | 963 | if (!access_ok(VERIFY_WRITE, dirent, count)) |
@@ -961,17 +967,12 @@ asmlinkage long compat_sys_getdents(unsigned int fd, | |||
961 | if (!f.file) | 967 | if (!f.file) |
962 | return -EBADF; | 968 | return -EBADF; |
963 | 969 | ||
964 | buf.current_dir = dirent; | 970 | error = iterate_dir(f.file, &buf.ctx); |
965 | buf.previous = NULL; | ||
966 | buf.count = count; | ||
967 | buf.error = 0; | ||
968 | |||
969 | error = vfs_readdir(f.file, compat_filldir, &buf); | ||
970 | if (error >= 0) | 971 | if (error >= 0) |
971 | error = buf.error; | 972 | error = buf.error; |
972 | lastdirent = buf.previous; | 973 | lastdirent = buf.previous; |
973 | if (lastdirent) { | 974 | if (lastdirent) { |
974 | if (put_user(f.file->f_pos, &lastdirent->d_off)) | 975 | if (put_user(buf.ctx.pos, &lastdirent->d_off)) |
975 | error = -EFAULT; | 976 | error = -EFAULT; |
976 | else | 977 | else |
977 | error = count - buf.count; | 978 | error = count - buf.count; |
@@ -983,6 +984,7 @@ asmlinkage long compat_sys_getdents(unsigned int fd, | |||
983 | #ifndef __ARCH_OMIT_COMPAT_SYS_GETDENTS64 | 984 | #ifndef __ARCH_OMIT_COMPAT_SYS_GETDENTS64 |
984 | 985 | ||
985 | struct compat_getdents_callback64 { | 986 | struct compat_getdents_callback64 { |
987 | struct dir_context ctx; | ||
986 | struct linux_dirent64 __user *current_dir; | 988 | struct linux_dirent64 __user *current_dir; |
987 | struct linux_dirent64 __user *previous; | 989 | struct linux_dirent64 __user *previous; |
988 | int count; | 990 | int count; |
@@ -1036,7 +1038,11 @@ asmlinkage long compat_sys_getdents64(unsigned int fd, | |||
1036 | { | 1038 | { |
1037 | struct fd f; | 1039 | struct fd f; |
1038 | struct linux_dirent64 __user * lastdirent; | 1040 | struct linux_dirent64 __user * lastdirent; |
1039 | struct compat_getdents_callback64 buf; | 1041 | struct compat_getdents_callback64 buf = { |
1042 | .ctx.actor = compat_filldir64, | ||
1043 | .current_dir = dirent, | ||
1044 | .count = count | ||
1045 | }; | ||
1040 | int error; | 1046 | int error; |
1041 | 1047 | ||
1042 | if (!access_ok(VERIFY_WRITE, dirent, count)) | 1048 | if (!access_ok(VERIFY_WRITE, dirent, count)) |
@@ -1046,17 +1052,12 @@ asmlinkage long compat_sys_getdents64(unsigned int fd, | |||
1046 | if (!f.file) | 1052 | if (!f.file) |
1047 | return -EBADF; | 1053 | return -EBADF; |
1048 | 1054 | ||
1049 | buf.current_dir = dirent; | 1055 | error = iterate_dir(f.file, &buf.ctx); |
1050 | buf.previous = NULL; | ||
1051 | buf.count = count; | ||
1052 | buf.error = 0; | ||
1053 | |||
1054 | error = vfs_readdir(f.file, compat_filldir64, &buf); | ||
1055 | if (error >= 0) | 1056 | if (error >= 0) |
1056 | error = buf.error; | 1057 | error = buf.error; |
1057 | lastdirent = buf.previous; | 1058 | lastdirent = buf.previous; |
1058 | if (lastdirent) { | 1059 | if (lastdirent) { |
1059 | typeof(lastdirent->d_off) d_off = f.file->f_pos; | 1060 | typeof(lastdirent->d_off) d_off = buf.ctx.pos; |
1060 | if (__put_user_unaligned(d_off, &lastdirent->d_off)) | 1061 | if (__put_user_unaligned(d_off, &lastdirent->d_off)) |
1061 | error = -EFAULT; | 1062 | error = -EFAULT; |
1062 | else | 1063 | else |