Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
0460b2a2
K
Kernel
项目概览
openeuler
/
Kernel
接近 2 年 前同步成功
通知
8
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
Kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
0460b2a2
编写于
4月 08, 2017
作者:
A
Al Viro
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
readdir: move compat syscalls from compat.c
Signed-off-by:
N
Al Viro
<
viro@zeniv.linux.org.uk
>
上级
4ada54ee
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
165 addition
and
162 deletion
+165
-162
fs/compat.c
fs/compat.c
+0
-162
fs/readdir.c
fs/readdir.c
+165
-0
未找到文件。
fs/compat.c
浏览文件 @
0460b2a2
...
...
@@ -548,168 +548,6 @@ COMPAT_SYSCALL_DEFINE5(mount, const char __user *, dev_name,
return
retval
;
}
struct
compat_old_linux_dirent
{
compat_ulong_t
d_ino
;
compat_ulong_t
d_offset
;
unsigned
short
d_namlen
;
char
d_name
[
1
];
};
struct
compat_readdir_callback
{
struct
dir_context
ctx
;
struct
compat_old_linux_dirent
__user
*
dirent
;
int
result
;
};
static
int
compat_fillonedir
(
struct
dir_context
*
ctx
,
const
char
*
name
,
int
namlen
,
loff_t
offset
,
u64
ino
,
unsigned
int
d_type
)
{
struct
compat_readdir_callback
*
buf
=
container_of
(
ctx
,
struct
compat_readdir_callback
,
ctx
);
struct
compat_old_linux_dirent
__user
*
dirent
;
compat_ulong_t
d_ino
;
if
(
buf
->
result
)
return
-
EINVAL
;
d_ino
=
ino
;
if
(
sizeof
(
d_ino
)
<
sizeof
(
ino
)
&&
d_ino
!=
ino
)
{
buf
->
result
=
-
EOVERFLOW
;
return
-
EOVERFLOW
;
}
buf
->
result
++
;
dirent
=
buf
->
dirent
;
if
(
!
access_ok
(
VERIFY_WRITE
,
dirent
,
(
unsigned
long
)(
dirent
->
d_name
+
namlen
+
1
)
-
(
unsigned
long
)
dirent
))
goto
efault
;
if
(
__put_user
(
d_ino
,
&
dirent
->
d_ino
)
||
__put_user
(
offset
,
&
dirent
->
d_offset
)
||
__put_user
(
namlen
,
&
dirent
->
d_namlen
)
||
__copy_to_user
(
dirent
->
d_name
,
name
,
namlen
)
||
__put_user
(
0
,
dirent
->
d_name
+
namlen
))
goto
efault
;
return
0
;
efault:
buf
->
result
=
-
EFAULT
;
return
-
EFAULT
;
}
COMPAT_SYSCALL_DEFINE3
(
old_readdir
,
unsigned
int
,
fd
,
struct
compat_old_linux_dirent
__user
*
,
dirent
,
unsigned
int
,
count
)
{
int
error
;
struct
fd
f
=
fdget_pos
(
fd
);
struct
compat_readdir_callback
buf
=
{
.
ctx
.
actor
=
compat_fillonedir
,
.
dirent
=
dirent
};
if
(
!
f
.
file
)
return
-
EBADF
;
error
=
iterate_dir
(
f
.
file
,
&
buf
.
ctx
);
if
(
buf
.
result
)
error
=
buf
.
result
;
fdput_pos
(
f
);
return
error
;
}
struct
compat_linux_dirent
{
compat_ulong_t
d_ino
;
compat_ulong_t
d_off
;
unsigned
short
d_reclen
;
char
d_name
[
1
];
};
struct
compat_getdents_callback
{
struct
dir_context
ctx
;
struct
compat_linux_dirent
__user
*
current_dir
;
struct
compat_linux_dirent
__user
*
previous
;
int
count
;
int
error
;
};
static
int
compat_filldir
(
struct
dir_context
*
ctx
,
const
char
*
name
,
int
namlen
,
loff_t
offset
,
u64
ino
,
unsigned
int
d_type
)
{
struct
compat_linux_dirent
__user
*
dirent
;
struct
compat_getdents_callback
*
buf
=
container_of
(
ctx
,
struct
compat_getdents_callback
,
ctx
);
compat_ulong_t
d_ino
;
int
reclen
=
ALIGN
(
offsetof
(
struct
compat_linux_dirent
,
d_name
)
+
namlen
+
2
,
sizeof
(
compat_long_t
));
buf
->
error
=
-
EINVAL
;
/* only used if we fail.. */
if
(
reclen
>
buf
->
count
)
return
-
EINVAL
;
d_ino
=
ino
;
if
(
sizeof
(
d_ino
)
<
sizeof
(
ino
)
&&
d_ino
!=
ino
)
{
buf
->
error
=
-
EOVERFLOW
;
return
-
EOVERFLOW
;
}
dirent
=
buf
->
previous
;
if
(
dirent
)
{
if
(
signal_pending
(
current
))
return
-
EINTR
;
if
(
__put_user
(
offset
,
&
dirent
->
d_off
))
goto
efault
;
}
dirent
=
buf
->
current_dir
;
if
(
__put_user
(
d_ino
,
&
dirent
->
d_ino
))
goto
efault
;
if
(
__put_user
(
reclen
,
&
dirent
->
d_reclen
))
goto
efault
;
if
(
copy_to_user
(
dirent
->
d_name
,
name
,
namlen
))
goto
efault
;
if
(
__put_user
(
0
,
dirent
->
d_name
+
namlen
))
goto
efault
;
if
(
__put_user
(
d_type
,
(
char
__user
*
)
dirent
+
reclen
-
1
))
goto
efault
;
buf
->
previous
=
dirent
;
dirent
=
(
void
__user
*
)
dirent
+
reclen
;
buf
->
current_dir
=
dirent
;
buf
->
count
-=
reclen
;
return
0
;
efault:
buf
->
error
=
-
EFAULT
;
return
-
EFAULT
;
}
COMPAT_SYSCALL_DEFINE3
(
getdents
,
unsigned
int
,
fd
,
struct
compat_linux_dirent
__user
*
,
dirent
,
unsigned
int
,
count
)
{
struct
fd
f
;
struct
compat_linux_dirent
__user
*
lastdirent
;
struct
compat_getdents_callback
buf
=
{
.
ctx
.
actor
=
compat_filldir
,
.
current_dir
=
dirent
,
.
count
=
count
};
int
error
;
if
(
!
access_ok
(
VERIFY_WRITE
,
dirent
,
count
))
return
-
EFAULT
;
f
=
fdget_pos
(
fd
);
if
(
!
f
.
file
)
return
-
EBADF
;
error
=
iterate_dir
(
f
.
file
,
&
buf
.
ctx
);
if
(
error
>=
0
)
error
=
buf
.
error
;
lastdirent
=
buf
.
previous
;
if
(
lastdirent
)
{
if
(
put_user
(
buf
.
ctx
.
pos
,
&
lastdirent
->
d_off
))
error
=
-
EFAULT
;
else
error
=
count
-
buf
.
count
;
}
fdput_pos
(
f
);
return
error
;
}
/*
* Exactly like fs/open.c:sys_open(), except that it doesn't set the
* O_LARGEFILE flag.
...
...
fs/readdir.c
浏览文件 @
0460b2a2
...
...
@@ -18,6 +18,7 @@
#include <linux/security.h>
#include <linux/syscalls.h>
#include <linux/unistd.h>
#include <linux/compat.h>
#include <linux/uaccess.h>
...
...
@@ -324,3 +325,167 @@ SYSCALL_DEFINE3(getdents64, unsigned int, fd,
fdput_pos
(
f
);
return
error
;
}
#ifdef CONFIG_COMPAT
struct
compat_old_linux_dirent
{
compat_ulong_t
d_ino
;
compat_ulong_t
d_offset
;
unsigned
short
d_namlen
;
char
d_name
[
1
];
};
struct
compat_readdir_callback
{
struct
dir_context
ctx
;
struct
compat_old_linux_dirent
__user
*
dirent
;
int
result
;
};
static
int
compat_fillonedir
(
struct
dir_context
*
ctx
,
const
char
*
name
,
int
namlen
,
loff_t
offset
,
u64
ino
,
unsigned
int
d_type
)
{
struct
compat_readdir_callback
*
buf
=
container_of
(
ctx
,
struct
compat_readdir_callback
,
ctx
);
struct
compat_old_linux_dirent
__user
*
dirent
;
compat_ulong_t
d_ino
;
if
(
buf
->
result
)
return
-
EINVAL
;
d_ino
=
ino
;
if
(
sizeof
(
d_ino
)
<
sizeof
(
ino
)
&&
d_ino
!=
ino
)
{
buf
->
result
=
-
EOVERFLOW
;
return
-
EOVERFLOW
;
}
buf
->
result
++
;
dirent
=
buf
->
dirent
;
if
(
!
access_ok
(
VERIFY_WRITE
,
dirent
,
(
unsigned
long
)(
dirent
->
d_name
+
namlen
+
1
)
-
(
unsigned
long
)
dirent
))
goto
efault
;
if
(
__put_user
(
d_ino
,
&
dirent
->
d_ino
)
||
__put_user
(
offset
,
&
dirent
->
d_offset
)
||
__put_user
(
namlen
,
&
dirent
->
d_namlen
)
||
__copy_to_user
(
dirent
->
d_name
,
name
,
namlen
)
||
__put_user
(
0
,
dirent
->
d_name
+
namlen
))
goto
efault
;
return
0
;
efault:
buf
->
result
=
-
EFAULT
;
return
-
EFAULT
;
}
COMPAT_SYSCALL_DEFINE3
(
old_readdir
,
unsigned
int
,
fd
,
struct
compat_old_linux_dirent
__user
*
,
dirent
,
unsigned
int
,
count
)
{
int
error
;
struct
fd
f
=
fdget_pos
(
fd
);
struct
compat_readdir_callback
buf
=
{
.
ctx
.
actor
=
compat_fillonedir
,
.
dirent
=
dirent
};
if
(
!
f
.
file
)
return
-
EBADF
;
error
=
iterate_dir
(
f
.
file
,
&
buf
.
ctx
);
if
(
buf
.
result
)
error
=
buf
.
result
;
fdput_pos
(
f
);
return
error
;
}
struct
compat_linux_dirent
{
compat_ulong_t
d_ino
;
compat_ulong_t
d_off
;
unsigned
short
d_reclen
;
char
d_name
[
1
];
};
struct
compat_getdents_callback
{
struct
dir_context
ctx
;
struct
compat_linux_dirent
__user
*
current_dir
;
struct
compat_linux_dirent
__user
*
previous
;
int
count
;
int
error
;
};
static
int
compat_filldir
(
struct
dir_context
*
ctx
,
const
char
*
name
,
int
namlen
,
loff_t
offset
,
u64
ino
,
unsigned
int
d_type
)
{
struct
compat_linux_dirent
__user
*
dirent
;
struct
compat_getdents_callback
*
buf
=
container_of
(
ctx
,
struct
compat_getdents_callback
,
ctx
);
compat_ulong_t
d_ino
;
int
reclen
=
ALIGN
(
offsetof
(
struct
compat_linux_dirent
,
d_name
)
+
namlen
+
2
,
sizeof
(
compat_long_t
));
buf
->
error
=
-
EINVAL
;
/* only used if we fail.. */
if
(
reclen
>
buf
->
count
)
return
-
EINVAL
;
d_ino
=
ino
;
if
(
sizeof
(
d_ino
)
<
sizeof
(
ino
)
&&
d_ino
!=
ino
)
{
buf
->
error
=
-
EOVERFLOW
;
return
-
EOVERFLOW
;
}
dirent
=
buf
->
previous
;
if
(
dirent
)
{
if
(
signal_pending
(
current
))
return
-
EINTR
;
if
(
__put_user
(
offset
,
&
dirent
->
d_off
))
goto
efault
;
}
dirent
=
buf
->
current_dir
;
if
(
__put_user
(
d_ino
,
&
dirent
->
d_ino
))
goto
efault
;
if
(
__put_user
(
reclen
,
&
dirent
->
d_reclen
))
goto
efault
;
if
(
copy_to_user
(
dirent
->
d_name
,
name
,
namlen
))
goto
efault
;
if
(
__put_user
(
0
,
dirent
->
d_name
+
namlen
))
goto
efault
;
if
(
__put_user
(
d_type
,
(
char
__user
*
)
dirent
+
reclen
-
1
))
goto
efault
;
buf
->
previous
=
dirent
;
dirent
=
(
void
__user
*
)
dirent
+
reclen
;
buf
->
current_dir
=
dirent
;
buf
->
count
-=
reclen
;
return
0
;
efault:
buf
->
error
=
-
EFAULT
;
return
-
EFAULT
;
}
COMPAT_SYSCALL_DEFINE3
(
getdents
,
unsigned
int
,
fd
,
struct
compat_linux_dirent
__user
*
,
dirent
,
unsigned
int
,
count
)
{
struct
fd
f
;
struct
compat_linux_dirent
__user
*
lastdirent
;
struct
compat_getdents_callback
buf
=
{
.
ctx
.
actor
=
compat_filldir
,
.
current_dir
=
dirent
,
.
count
=
count
};
int
error
;
if
(
!
access_ok
(
VERIFY_WRITE
,
dirent
,
count
))
return
-
EFAULT
;
f
=
fdget_pos
(
fd
);
if
(
!
f
.
file
)
return
-
EBADF
;
error
=
iterate_dir
(
f
.
file
,
&
buf
.
ctx
);
if
(
error
>=
0
)
error
=
buf
.
error
;
lastdirent
=
buf
.
previous
;
if
(
lastdirent
)
{
if
(
put_user
(
buf
.
ctx
.
pos
,
&
lastdirent
->
d_off
))
error
=
-
EFAULT
;
else
error
=
count
-
buf
.
count
;
}
fdput_pos
(
f
);
return
error
;
}
#endif
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录