Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
80f0cce6
Commit
80f0cce6
authored
Apr 08, 2017
by
Al Viro
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fcntl: move compat syscalls from compat.c
Signed-off-by:
Al Viro
<
viro@zeniv.linux.org.uk
>
parent
0460b2a2
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
157 additions
and
154 deletions
+157
-154
fs/compat.c
fs/compat.c
+0
-154
fs/fcntl.c
fs/fcntl.c
+157
-0
No files found.
fs/compat.c
View file @
80f0cce6
...
...
@@ -137,160 +137,6 @@ COMPAT_SYSCALL_DEFINE2(newfstat, unsigned int, fd,
return
error
;
}
static
int
get_compat_flock
(
struct
flock
*
kfl
,
struct
compat_flock
__user
*
ufl
)
{
if
(
!
access_ok
(
VERIFY_READ
,
ufl
,
sizeof
(
*
ufl
))
||
__get_user
(
kfl
->
l_type
,
&
ufl
->
l_type
)
||
__get_user
(
kfl
->
l_whence
,
&
ufl
->
l_whence
)
||
__get_user
(
kfl
->
l_start
,
&
ufl
->
l_start
)
||
__get_user
(
kfl
->
l_len
,
&
ufl
->
l_len
)
||
__get_user
(
kfl
->
l_pid
,
&
ufl
->
l_pid
))
return
-
EFAULT
;
return
0
;
}
static
int
put_compat_flock
(
struct
flock
*
kfl
,
struct
compat_flock
__user
*
ufl
)
{
if
(
!
access_ok
(
VERIFY_WRITE
,
ufl
,
sizeof
(
*
ufl
))
||
__put_user
(
kfl
->
l_type
,
&
ufl
->
l_type
)
||
__put_user
(
kfl
->
l_whence
,
&
ufl
->
l_whence
)
||
__put_user
(
kfl
->
l_start
,
&
ufl
->
l_start
)
||
__put_user
(
kfl
->
l_len
,
&
ufl
->
l_len
)
||
__put_user
(
kfl
->
l_pid
,
&
ufl
->
l_pid
))
return
-
EFAULT
;
return
0
;
}
#ifndef HAVE_ARCH_GET_COMPAT_FLOCK64
static
int
get_compat_flock64
(
struct
flock
*
kfl
,
struct
compat_flock64
__user
*
ufl
)
{
if
(
!
access_ok
(
VERIFY_READ
,
ufl
,
sizeof
(
*
ufl
))
||
__get_user
(
kfl
->
l_type
,
&
ufl
->
l_type
)
||
__get_user
(
kfl
->
l_whence
,
&
ufl
->
l_whence
)
||
__get_user
(
kfl
->
l_start
,
&
ufl
->
l_start
)
||
__get_user
(
kfl
->
l_len
,
&
ufl
->
l_len
)
||
__get_user
(
kfl
->
l_pid
,
&
ufl
->
l_pid
))
return
-
EFAULT
;
return
0
;
}
#endif
#ifndef HAVE_ARCH_PUT_COMPAT_FLOCK64
static
int
put_compat_flock64
(
struct
flock
*
kfl
,
struct
compat_flock64
__user
*
ufl
)
{
if
(
!
access_ok
(
VERIFY_WRITE
,
ufl
,
sizeof
(
*
ufl
))
||
__put_user
(
kfl
->
l_type
,
&
ufl
->
l_type
)
||
__put_user
(
kfl
->
l_whence
,
&
ufl
->
l_whence
)
||
__put_user
(
kfl
->
l_start
,
&
ufl
->
l_start
)
||
__put_user
(
kfl
->
l_len
,
&
ufl
->
l_len
)
||
__put_user
(
kfl
->
l_pid
,
&
ufl
->
l_pid
))
return
-
EFAULT
;
return
0
;
}
#endif
static
unsigned
int
convert_fcntl_cmd
(
unsigned
int
cmd
)
{
switch
(
cmd
)
{
case
F_GETLK64
:
return
F_GETLK
;
case
F_SETLK64
:
return
F_SETLK
;
case
F_SETLKW64
:
return
F_SETLKW
;
}
return
cmd
;
}
COMPAT_SYSCALL_DEFINE3
(
fcntl64
,
unsigned
int
,
fd
,
unsigned
int
,
cmd
,
compat_ulong_t
,
arg
)
{
mm_segment_t
old_fs
;
struct
flock
f
;
long
ret
;
unsigned
int
conv_cmd
;
switch
(
cmd
)
{
case
F_GETLK
:
case
F_SETLK
:
case
F_SETLKW
:
ret
=
get_compat_flock
(
&
f
,
compat_ptr
(
arg
));
if
(
ret
!=
0
)
break
;
old_fs
=
get_fs
();
set_fs
(
KERNEL_DS
);
ret
=
sys_fcntl
(
fd
,
cmd
,
(
unsigned
long
)
&
f
);
set_fs
(
old_fs
);
if
(
cmd
==
F_GETLK
&&
ret
==
0
)
{
/* GETLK was successful and we need to return the data...
* but it needs to fit in the compat structure.
* l_start shouldn't be too big, unless the original
* start + end is greater than COMPAT_OFF_T_MAX, in which
* case the app was asking for trouble, so we return
* -EOVERFLOW in that case.
* l_len could be too big, in which case we just truncate it,
* and only allow the app to see that part of the conflicting
* lock that might make sense to it anyway
*/
if
(
f
.
l_start
>
COMPAT_OFF_T_MAX
)
ret
=
-
EOVERFLOW
;
if
(
f
.
l_len
>
COMPAT_OFF_T_MAX
)
f
.
l_len
=
COMPAT_OFF_T_MAX
;
if
(
ret
==
0
)
ret
=
put_compat_flock
(
&
f
,
compat_ptr
(
arg
));
}
break
;
case
F_GETLK64
:
case
F_SETLK64
:
case
F_SETLKW64
:
case
F_OFD_GETLK
:
case
F_OFD_SETLK
:
case
F_OFD_SETLKW
:
ret
=
get_compat_flock64
(
&
f
,
compat_ptr
(
arg
));
if
(
ret
!=
0
)
break
;
old_fs
=
get_fs
();
set_fs
(
KERNEL_DS
);
conv_cmd
=
convert_fcntl_cmd
(
cmd
);
ret
=
sys_fcntl
(
fd
,
conv_cmd
,
(
unsigned
long
)
&
f
);
set_fs
(
old_fs
);
if
((
conv_cmd
==
F_GETLK
||
conv_cmd
==
F_OFD_GETLK
)
&&
ret
==
0
)
{
/* need to return lock information - see above for commentary */
if
(
f
.
l_start
>
COMPAT_LOFF_T_MAX
)
ret
=
-
EOVERFLOW
;
if
(
f
.
l_len
>
COMPAT_LOFF_T_MAX
)
f
.
l_len
=
COMPAT_LOFF_T_MAX
;
if
(
ret
==
0
)
ret
=
put_compat_flock64
(
&
f
,
compat_ptr
(
arg
));
}
break
;
default:
ret
=
sys_fcntl
(
fd
,
cmd
,
arg
);
break
;
}
return
ret
;
}
COMPAT_SYSCALL_DEFINE3
(
fcntl
,
unsigned
int
,
fd
,
unsigned
int
,
cmd
,
compat_ulong_t
,
arg
)
{
switch
(
cmd
)
{
case
F_GETLK64
:
case
F_SETLK64
:
case
F_SETLKW64
:
case
F_OFD_GETLK
:
case
F_OFD_SETLK
:
case
F_OFD_SETLKW
:
return
-
EINVAL
;
}
return
compat_sys_fcntl64
(
fd
,
cmd
,
arg
);
}
/* A write operation does a read from user space and vice versa */
#define vrfy_dir(type) ((type) == READ ? VERIFY_WRITE : VERIFY_READ)
...
...
fs/fcntl.c
View file @
80f0cce6
...
...
@@ -23,6 +23,7 @@
#include <linux/pid_namespace.h>
#include <linux/user_namespace.h>
#include <linux/shmem_fs.h>
#include <linux/compat.h>
#include <asm/poll.h>
#include <asm/siginfo.h>
...
...
@@ -420,6 +421,162 @@ SYSCALL_DEFINE3(fcntl64, unsigned int, fd, unsigned int, cmd,
}
#endif
#ifdef CONFIG_COMPAT
static
int
get_compat_flock
(
struct
flock
*
kfl
,
struct
compat_flock
__user
*
ufl
)
{
if
(
!
access_ok
(
VERIFY_READ
,
ufl
,
sizeof
(
*
ufl
))
||
__get_user
(
kfl
->
l_type
,
&
ufl
->
l_type
)
||
__get_user
(
kfl
->
l_whence
,
&
ufl
->
l_whence
)
||
__get_user
(
kfl
->
l_start
,
&
ufl
->
l_start
)
||
__get_user
(
kfl
->
l_len
,
&
ufl
->
l_len
)
||
__get_user
(
kfl
->
l_pid
,
&
ufl
->
l_pid
))
return
-
EFAULT
;
return
0
;
}
static
int
put_compat_flock
(
struct
flock
*
kfl
,
struct
compat_flock
__user
*
ufl
)
{
if
(
!
access_ok
(
VERIFY_WRITE
,
ufl
,
sizeof
(
*
ufl
))
||
__put_user
(
kfl
->
l_type
,
&
ufl
->
l_type
)
||
__put_user
(
kfl
->
l_whence
,
&
ufl
->
l_whence
)
||
__put_user
(
kfl
->
l_start
,
&
ufl
->
l_start
)
||
__put_user
(
kfl
->
l_len
,
&
ufl
->
l_len
)
||
__put_user
(
kfl
->
l_pid
,
&
ufl
->
l_pid
))
return
-
EFAULT
;
return
0
;
}
#ifndef HAVE_ARCH_GET_COMPAT_FLOCK64
static
int
get_compat_flock64
(
struct
flock
*
kfl
,
struct
compat_flock64
__user
*
ufl
)
{
if
(
!
access_ok
(
VERIFY_READ
,
ufl
,
sizeof
(
*
ufl
))
||
__get_user
(
kfl
->
l_type
,
&
ufl
->
l_type
)
||
__get_user
(
kfl
->
l_whence
,
&
ufl
->
l_whence
)
||
__get_user
(
kfl
->
l_start
,
&
ufl
->
l_start
)
||
__get_user
(
kfl
->
l_len
,
&
ufl
->
l_len
)
||
__get_user
(
kfl
->
l_pid
,
&
ufl
->
l_pid
))
return
-
EFAULT
;
return
0
;
}
#endif
#ifndef HAVE_ARCH_PUT_COMPAT_FLOCK64
static
int
put_compat_flock64
(
struct
flock
*
kfl
,
struct
compat_flock64
__user
*
ufl
)
{
if
(
!
access_ok
(
VERIFY_WRITE
,
ufl
,
sizeof
(
*
ufl
))
||
__put_user
(
kfl
->
l_type
,
&
ufl
->
l_type
)
||
__put_user
(
kfl
->
l_whence
,
&
ufl
->
l_whence
)
||
__put_user
(
kfl
->
l_start
,
&
ufl
->
l_start
)
||
__put_user
(
kfl
->
l_len
,
&
ufl
->
l_len
)
||
__put_user
(
kfl
->
l_pid
,
&
ufl
->
l_pid
))
return
-
EFAULT
;
return
0
;
}
#endif
static
unsigned
int
convert_fcntl_cmd
(
unsigned
int
cmd
)
{
switch
(
cmd
)
{
case
F_GETLK64
:
return
F_GETLK
;
case
F_SETLK64
:
return
F_SETLK
;
case
F_SETLKW64
:
return
F_SETLKW
;
}
return
cmd
;
}
COMPAT_SYSCALL_DEFINE3
(
fcntl64
,
unsigned
int
,
fd
,
unsigned
int
,
cmd
,
compat_ulong_t
,
arg
)
{
mm_segment_t
old_fs
;
struct
flock
f
;
long
ret
;
unsigned
int
conv_cmd
;
switch
(
cmd
)
{
case
F_GETLK
:
case
F_SETLK
:
case
F_SETLKW
:
ret
=
get_compat_flock
(
&
f
,
compat_ptr
(
arg
));
if
(
ret
!=
0
)
break
;
old_fs
=
get_fs
();
set_fs
(
KERNEL_DS
);
ret
=
sys_fcntl
(
fd
,
cmd
,
(
unsigned
long
)
&
f
);
set_fs
(
old_fs
);
if
(
cmd
==
F_GETLK
&&
ret
==
0
)
{
/* GETLK was successful and we need to return the data...
* but it needs to fit in the compat structure.
* l_start shouldn't be too big, unless the original
* start + end is greater than COMPAT_OFF_T_MAX, in which
* case the app was asking for trouble, so we return
* -EOVERFLOW in that case.
* l_len could be too big, in which case we just truncate it,
* and only allow the app to see that part of the conflicting
* lock that might make sense to it anyway
*/
if
(
f
.
l_start
>
COMPAT_OFF_T_MAX
)
ret
=
-
EOVERFLOW
;
if
(
f
.
l_len
>
COMPAT_OFF_T_MAX
)
f
.
l_len
=
COMPAT_OFF_T_MAX
;
if
(
ret
==
0
)
ret
=
put_compat_flock
(
&
f
,
compat_ptr
(
arg
));
}
break
;
case
F_GETLK64
:
case
F_SETLK64
:
case
F_SETLKW64
:
case
F_OFD_GETLK
:
case
F_OFD_SETLK
:
case
F_OFD_SETLKW
:
ret
=
get_compat_flock64
(
&
f
,
compat_ptr
(
arg
));
if
(
ret
!=
0
)
break
;
old_fs
=
get_fs
();
set_fs
(
KERNEL_DS
);
conv_cmd
=
convert_fcntl_cmd
(
cmd
);
ret
=
sys_fcntl
(
fd
,
conv_cmd
,
(
unsigned
long
)
&
f
);
set_fs
(
old_fs
);
if
((
conv_cmd
==
F_GETLK
||
conv_cmd
==
F_OFD_GETLK
)
&&
ret
==
0
)
{
/* need to return lock information - see above for commentary */
if
(
f
.
l_start
>
COMPAT_LOFF_T_MAX
)
ret
=
-
EOVERFLOW
;
if
(
f
.
l_len
>
COMPAT_LOFF_T_MAX
)
f
.
l_len
=
COMPAT_LOFF_T_MAX
;
if
(
ret
==
0
)
ret
=
put_compat_flock64
(
&
f
,
compat_ptr
(
arg
));
}
break
;
default:
ret
=
sys_fcntl
(
fd
,
cmd
,
arg
);
break
;
}
return
ret
;
}
COMPAT_SYSCALL_DEFINE3
(
fcntl
,
unsigned
int
,
fd
,
unsigned
int
,
cmd
,
compat_ulong_t
,
arg
)
{
switch
(
cmd
)
{
case
F_GETLK64
:
case
F_SETLK64
:
case
F_SETLKW64
:
case
F_OFD_GETLK
:
case
F_OFD_SETLK
:
case
F_OFD_SETLKW
:
return
-
EINVAL
;
}
return
compat_sys_fcntl64
(
fd
,
cmd
,
arg
);
}
#endif
/* Table to convert sigio signal codes into poll band bitmaps */
static
const
long
band_table
[
NSIGPOLL
]
=
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment