Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
videolan
vlc
Commits
d9799c19
Commit
d9799c19
authored
Jun 06, 2008
by
Rémi Denis-Courmont
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Bring the root wrapper back
parent
793c4fa6
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
62 additions
and
283 deletions
+62
-283
src/Makefile.am
src/Makefile.am
+5
-1
src/network/rootwrap.c
src/network/rootwrap.c
+57
-282
No files found.
src/Makefile.am
View file @
d9799c19
...
...
@@ -427,9 +427,12 @@ misc/revision.c:
# Building vlc
###############################################################################
EXTRA_PROGRAMS
=
vlc
EXTRA_PROGRAMS
=
vlc
vlc-wrapper
if
BUILD_VLC
bin_PROGRAMS
=
vlc
if
!HAVE_WIN32
bin_PROGRAMS
+=
vlc-wrapper
endif
endif
EXTRA_vlc_SOURCES
=
vlc.c winvlc.c
...
...
@@ -438,6 +441,7 @@ vlc_SOURCES = vlc.c
else
vlc_SOURCES
=
winvlc.c
endif
vlc_wrapper_SOURCES
=
network/rootwrap.c
vlc_DEPENDENCIES
=
$(DATA_win32_rc)
libvlc.la
...
...
src/network/rootwrap.c
View file @
d9799c19
/*****************************************************************************
* rootwrap.c
*****************************************************************************
* Copyright © 2005 Rémi Denis-Courmont
* $Id$
*
* Author: Rémi Denis-Courmont <rem # videolan.org>
* Copyright © 2005-2008 Rémi Denis-Courmont
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
...
...
@@ -25,12 +22,6 @@
# include <config.h>
#endif
#if defined (HAVE_GETEUID) && !defined (SYS_BEOS)
# define ENABLE_ROOTWRAP 1
#endif
#ifdef ENABLE_ROOTWRAP
#include <stdlib.h>
/* exit() */
#include <stdio.h>
#include <string.h>
...
...
@@ -38,19 +29,13 @@
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/socket.h>
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#include <sys/uio.h>
#include <sys/resource.h>
/* getrlimit() */
#include <sys/wait.h>
#include <sys/un.h>
#include <pwd.h>
/* getpwnam(), getpwuid() */
#include <grp.h>
/* setgroups() */
#include <sched.h>
#include <errno.h>
#include <netinet/in.h>
#include <pthread.h>
#if defined (AF_INET6) && !defined (IPV6_V6ONLY)
# warning Uho, your IPv6 support is broken and has been disabled. Fix your C library.
...
...
@@ -61,66 +46,20 @@
# define AF_LOCAL AF_UNIX
#endif
/*#ifndef HAVE_CLEARENV
extern char **environ;
static int clearenv (void)
{
environ = NULL;
return 0;
}
#endif*/
/**
* Tries to find a real non-root user to use
*/
static
struct
passwd
*
guess_user
(
void
)
{
const
char
*
name
;
struct
passwd
*
pw
;
uid_t
uid
;
/* Try real UID */
uid
=
getuid
();
if
(
uid
)
if
((
pw
=
getpwuid
(
uid
))
!=
NULL
)
return
pw
;
/* Try sudo */
name
=
getenv
(
"SUDO_USER"
);
if
(
name
!=
NULL
)
if
((
pw
=
getpwnam
(
name
))
!=
NULL
)
return
pw
;
/* Try VLC_USER */
name
=
getenv
(
"VLC_USER"
);
if
(
name
!=
NULL
)
if
((
pw
=
getpwnam
(
name
))
!=
NULL
)
return
pw
;
/* Try vlc */
if
((
pw
=
getpwnam
(
"vlc"
))
!=
NULL
)
return
pw
;
return
getpwuid
(
0
);
}
static
int
is_allowed_port
(
uint16_t
port
)
static
inline
int
is_allowed_port
(
uint16_t
port
)
{
port
=
ntohs
(
port
);
return
(
port
==
80
)
||
(
port
==
443
)
||
(
port
==
554
);
}
static
int
send_err
(
int
fd
,
int
err
)
static
in
line
in
t
send_err
(
int
fd
,
int
err
)
{
return
send
(
fd
,
&
err
,
sizeof
(
err
),
0
)
==
sizeof
(
err
)
?
0
:
-
1
;
}
/**
*
Ugly POSIX(?) code to pass
a file descriptor to another process
*
Send
a file descriptor to another process
*/
static
int
send_fd
(
int
p
,
int
fd
)
{
...
...
@@ -158,10 +97,6 @@ static void rootprocess (int fd)
{
struct
sockaddr_storage
ss
;
/* TODO:
* - use libcap if available,
* - call chroot
*/
while
(
recv
(
fd
,
&
ss
,
sizeof
(
ss
),
0
)
==
sizeof
(
ss
))
{
unsigned
len
;
...
...
@@ -218,236 +153,76 @@ static void rootprocess (int fd)
}
}
static
int
rootwrap_sock
=
-
1
;
static
pid_t
rootwrap_pid
=
-
1
;
static
void
close_rootwrap
(
void
)
{
close
(
rootwrap_sock
);
waitpid
(
rootwrap_pid
,
NULL
,
0
);
}
/* TODO?
* - use libcap if available,
* - call chroot
*/
void
rootwrap
(
void
)
int
main
(
int
argc
,
char
*
argv
[]
)
{
struct
rlimit
lim
;
int
fd
,
pair
[
2
];
struct
passwd
*
pw
;
uid_t
u
;
u
=
geteuid
();
/* Are we running with root privileges? */
if
(
u
!=
0
)
{
setuid
(
u
);
return
;
}
/* Make sure 0, 1 and 2 are opened, and only these. */
if
(
getrlimit
(
RLIMIT_NOFILE
,
&
lim
))
exit
(
1
);
for
(
fd
=
3
;
((
unsigned
)
fd
)
<
lim
.
rlim_cur
;
fd
++
)
close
(
fd
);
fd
=
dup
(
2
);
if
(
fd
<=
2
)
exit
(
1
);
close
(
fd
);
fputs
(
"starting VLC root wrapper..."
,
stderr
);
pw
=
guess_user
();
if
(
pw
==
NULL
)
return
;
/* Should we rather print an error and exit ? */
u
=
pw
->
pw_uid
,
fprintf
(
stderr
,
" using UID %u (%s)
\n
"
,
(
unsigned
)
u
,
pw
->
pw_name
);
if
(
u
==
0
)
{
fputs
(
"***************************************
\n
"
"* Running VLC as root is discouraged. *
\n
"
"***************************************
\n
"
"
\n
"
" It is potentially dangerous, "
"and might not even work properly.
\n
"
,
stderr
);
return
;
}
/* GID */
initgroups
(
pw
->
pw_name
,
pw
->
pw_gid
);
setgid
(
pw
->
pw_gid
);
/* Support for dynamically opening RTSP, HTTP and HTTP/SSL ports */
int
pair
[
2
];
if
(
socketpair
(
AF_LOCAL
,
SOCK_STREAM
,
0
,
pair
))
{
perror
(
"socketpair"
);
goto
nofork
;
}
return
1
;
if
(
pair
[
0
]
<
3
)
goto
error
;
/* we want 0, 1 and 2 open */
switch
(
rootwrap_pid
=
fork
())
pid_t
pid
=
fork
();
switch
(
pid
)
{
case
-
1
:
perror
(
"fork"
);
close
(
pair
[
0
]);
close
(
pair
[
1
]);
break
;
goto
error
;
case
0
:
close
(
0
);
close
(
1
);
close
(
2
);
{
int
null
=
open
(
"/dev/null"
,
O_RDWR
);
if
(
null
!=
-
1
)
{
dup2
(
null
,
0
);
dup2
(
null
,
1
);
dup2
(
null
,
2
);
close
(
null
);
}
close
(
pair
[
0
]);
setsid
();
rootprocess
(
pair
[
1
]);
exit
(
0
);
default:
close
(
pair
[
1
]);
rootwrap_sock
=
pair
[
0
];
break
;
}
nofork:
/* UID */
setuid
(
u
);
atexit
(
close_rootwrap
);
}
/**
* Ugly POSIX(?) code to receive a file descriptor from another process
*/
static
int
recv_fd
(
int
p
)
{
struct
msghdr
hdr
;
struct
iovec
iov
;
struct
cmsghdr
*
cmsg
;
int
val
,
fd
;
char
buf
[
CMSG_SPACE
(
sizeof
(
fd
))];
hdr
.
msg_name
=
NULL
;
hdr
.
msg_namelen
=
0
;
hdr
.
msg_iov
=
&
iov
;
hdr
.
msg_iovlen
=
1
;
hdr
.
msg_control
=
buf
;
hdr
.
msg_controllen
=
sizeof
(
buf
);
iov
.
iov_base
=
&
val
;
iov
.
iov_len
=
sizeof
(
val
);
if
(
recvmsg
(
p
,
&
hdr
,
0
)
!=
sizeof
(
val
))
return
-
1
;
for
(
cmsg
=
CMSG_FIRSTHDR
(
&
hdr
);
cmsg
!=
NULL
;
cmsg
=
CMSG_NXTHDR
(
&
hdr
,
cmsg
))
{
if
((
cmsg
->
cmsg_level
==
SOL_SOCKET
)
&&
(
cmsg
->
cmsg_type
=
SCM_RIGHTS
)
&&
(
cmsg
->
cmsg_len
>=
CMSG_LEN
(
sizeof
(
fd
))))
{
memcpy
(
&
fd
,
CMSG_DATA
(
cmsg
),
sizeof
(
fd
));
return
fd
;
}
}
return
-
1
;
}
/**
* Tries to obtain a bound TCP socket from the root process
*/
int
rootwrap_bind
(
int
family
,
int
socktype
,
int
protocol
,
const
struct
sockaddr
*
addr
,
size_t
alen
)
{
/* can't use libvlc */
static
pthread_mutex_t
mutex
=
PTHREAD_MUTEX_INITIALIZER
;
struct
sockaddr_storage
ss
;
int
fd
;
close
(
pair
[
1
]);
pair
[
1
]
=
-
1
;
if
(
rootwrap_sock
==
-
1
)
{
errno
=
EACCES
;
return
-
1
;
}
switch
(
family
)
{
case
AF_INET
:
if
(
alen
<
sizeof
(
struct
sockaddr_in
))
{
errno
=
EINVAL
;
return
-
1
;
}
break
;
char
buf
[
21
];
snprintf
(
buf
,
sizeof
(
buf
),
"%d"
,
pair
[
0
]);
setenv
(
"VLC_ROOTWRAP_SOCK"
,
buf
,
1
);
#ifdef AF_INET6
case
AF_INET6
:
if
(
alen
<
sizeof
(
struct
sockaddr_in6
))
{
errno
=
EINVAL
;
return
-
1
;
}
break
;
/* Support for real-time priorities */
#ifdef RLIMIT_RTPRIO
struct
rlimit
rlim
;
rlim
.
rlim_max
=
rlim
.
rlim_cur
=
sched_get_priority_min
(
SCHED_RR
)
+
24
;
setrlimit
(
RLIMIT_RTPRIO
,
&
rlim
);
#endif
default:
errno
=
EAFNOSUPPORT
;
return
-
1
;
}
if
(
family
!=
addr
->
sa_family
)
{
errno
=
EAFNOSUPPORT
;
return
-
1
;
}
/* Only TCP is implemented at the moment */
if
((
socktype
!=
SOCK_STREAM
)
||
(
protocol
&&
(
protocol
!=
IPPROTO_TCP
)))
{
errno
=
EACCES
;
return
-
1
;
}
memset
(
&
ss
,
0
,
sizeof
(
ss
));
memcpy
(
&
ss
,
addr
,
alen
>
sizeof
(
ss
)
?
sizeof
(
ss
)
:
alen
);
pthread_mutex_lock
(
&
mutex
);
if
(
send
(
rootwrap_sock
,
&
ss
,
sizeof
(
ss
),
0
)
!=
sizeof
(
ss
))
return
-
1
;
fd
=
recv_fd
(
rootwrap_sock
);
pthread_mutex_unlock
(
&
mutex
);
setuid
(
getuid
());
if
(
fd
!=
-
1
)
{
int
val
;
val
=
fcntl
(
fd
,
F_GETFL
,
0
);
fcntl
(
fd
,
F_SETFL
,
((
val
!=
-
1
)
?
val
:
0
)
|
O_NONBLOCK
);
}
return
fd
;
}
#else
# include <stddef.h>
struct
sockaddr
;
void
rootwrap
(
void
)
{
}
if
(
!
setuid
(
0
))
/* sanity check: we cannot get root back */
exit
(
1
);
int
rootwrap_bind
(
int
family
,
int
socktype
,
int
protocol
,
const
struct
sockaddr
*
addr
,
size_t
alen
)
{
(
void
)
family
;
(
void
)
socktype
;
(
void
)
protocol
;
(
void
)
addr
;
(
void
)
alen
;
return
-
1
;
/* Yeah, the user can force to execute just about anything from here.
* But we've dropped privileges, so it does not matter. */
if
(
strlen
(
argv
[
0
])
<
sizeof
(
"-wrapper"
))
goto
error
;
argv
[
0
][
strlen
(
argv
[
0
])
-
strlen
(
"-wrapper"
)]
=
'\0'
;
(
void
)
argc
;
if
(
execvp
(
argv
[
0
],
argv
))
perror
(
argv
[
0
]);
error:
close
(
pair
[
0
]);
if
(
pair
[
1
]
!=
-
1
)
close
(
pair
[
1
]);
return
1
;
}
#endif
/* ENABLE_ROOTWRAP */
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