~ubuntu-branches/ubuntu/maverick/vlc/maverick

« back to all changes in this revision

Viewing changes to bin/rootwrap.c

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler
  • Date: 2008-09-17 21:56:14 UTC
  • mfrom: (1.1.17 upstream)
  • Revision ID: james.westby@ubuntu.com-20080917215614-tj0vx8xzd57e52t8
Tags: 0.9.2-1ubuntu1
* New Upstream Release, exception granted by
    - dktrkranz, norsetto, Hobbsee (via irc). LP: #270404

Changes done in ubuntu:

* add libxul-dev to build-depends
* make sure that vlc is build against libxul in configure. This doesn't
  change anything in the package, but makes it more robust if building
  in an 'unclean' chroot or when modifying the package.
* debian/control: make Vcs-* fields point to the motumedia branch
* add libx264-dev and libass-dev to build-depends
  LP: #210354, #199870
* actually enable libass support by passing --enable-libass to configure
* enable libdca: add libdca-dev to build depends and --enable-libdca
* install the x264 plugin.

Changes already in the pkg-multimedia branch in debian:

* don't install usr/share/vlc/mozilla in debian/mozilla-plugin-vlc.install  
* new upstream .desktop file now registers flash video mimetype LP: #261567
* add Xb-Npp-Applications to mozilla-plugin-vlc
* remove duplicate entries in debian/vlc-nox.install

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*****************************************************************************
 
2
 * rootwrap.c
 
3
 *****************************************************************************
 
4
 * Copyright © 2005-2008 Rémi Denis-Courmont
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or modify
 
7
 * it under the terms of the GNU General Public License as published by
 
8
 * the Free Software Foundation; either version 2 of the License, or
 
9
 * (at your option) any later version.
 
10
 *
 
11
 * This program is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 * GNU General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program; if not, write to the Free Software
 
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 
19
 *****************************************************************************/
 
20
 
 
21
#if HAVE_CONFIG_H
 
22
# include <config.h>
 
23
#endif
 
24
 
 
25
#include <stdlib.h> /* exit() */
 
26
#include <stdio.h>
 
27
#include <string.h>
 
28
 
 
29
#include <sys/types.h>
 
30
#include <unistd.h>
 
31
#include <fcntl.h>
 
32
#include <sys/stat.h>
 
33
#include <sys/socket.h>
 
34
#include <sys/uio.h>
 
35
#include <sys/resource.h> /* getrlimit() */
 
36
#include <sched.h>
 
37
#include <errno.h>
 
38
#include <netinet/in.h>
 
39
 
 
40
#if defined (AF_INET6) && !defined (IPV6_V6ONLY)
 
41
# warning Uho, your IPv6 support is broken and has been disabled. Fix your C library.
 
42
# undef AF_INET6
 
43
#endif
 
44
 
 
45
#ifndef AF_LOCAL
 
46
# define AF_LOCAL AF_UNIX
 
47
#endif
 
48
 
 
49
static inline int is_allowed_port (uint16_t port)
 
50
{
 
51
    port = ntohs (port);
 
52
    return (port == 80) || (port == 443) || (port == 554);
 
53
}
 
54
 
 
55
 
 
56
static inline int send_err (int fd, int err)
 
57
{
 
58
    return send (fd, &err, sizeof (err), 0) == sizeof (err) ? 0 : -1;
 
59
}
 
60
 
 
61
/**
 
62
 * Send a file descriptor to another process
 
63
 */
 
64
static int send_fd (int p, int fd)
 
65
{
 
66
    struct msghdr hdr;
 
67
    struct iovec iov;
 
68
    struct cmsghdr *cmsg;
 
69
    char buf[CMSG_SPACE (sizeof (fd))];
 
70
    int val = 0;
 
71
 
 
72
    hdr.msg_name = NULL;
 
73
    hdr.msg_namelen = 0;
 
74
    hdr.msg_iov = &iov;
 
75
    hdr.msg_iovlen = 1;
 
76
    hdr.msg_control = buf;
 
77
    hdr.msg_controllen = sizeof (buf);
 
78
 
 
79
    iov.iov_base = &val;
 
80
    iov.iov_len = sizeof (val);
 
81
 
 
82
    cmsg = CMSG_FIRSTHDR (&hdr);
 
83
    cmsg->cmsg_level = SOL_SOCKET;
 
84
    cmsg->cmsg_type = SCM_RIGHTS;
 
85
    cmsg->cmsg_len = CMSG_LEN (sizeof (fd));
 
86
    memcpy (CMSG_DATA (cmsg), &fd, sizeof (fd));
 
87
    hdr.msg_controllen = cmsg->cmsg_len;
 
88
 
 
89
    return sendmsg (p, &hdr, 0) == sizeof (val) ? 0 : -1;
 
90
}
 
91
 
 
92
 
 
93
/**
 
94
 * Background process run as root to open privileged TCP ports.
 
95
 */
 
96
static void rootprocess (int fd)
 
97
{
 
98
    struct sockaddr_storage ss;
 
99
 
 
100
    while (recv (fd, &ss, sizeof (ss), 0) == sizeof (ss))
 
101
    {
 
102
        unsigned len;
 
103
        int sock;
 
104
 
 
105
        switch (ss.ss_family)
 
106
        {
 
107
            case AF_INET:
 
108
                if (!is_allowed_port (((struct sockaddr_in *)&ss)->sin_port))
 
109
                {
 
110
                    if (send_err (fd, EACCES))
 
111
                        return;
 
112
                    continue;
 
113
                }
 
114
                len = sizeof (struct sockaddr_in);
 
115
                break;
 
116
 
 
117
#ifdef AF_INET6
 
118
            case AF_INET6:
 
119
                if (!is_allowed_port (((struct sockaddr_in6 *)&ss)->sin6_port))
 
120
                {
 
121
                    if (send_err (fd, EACCES))
 
122
                        return;
 
123
                    continue;
 
124
                }
 
125
                len = sizeof (struct sockaddr_in6);
 
126
                break;
 
127
#endif
 
128
 
 
129
            default:
 
130
                if (send_err (fd, EAFNOSUPPORT))
 
131
                    return;
 
132
                continue;
 
133
        }
 
134
 
 
135
        sock = socket (ss.ss_family, SOCK_STREAM, IPPROTO_TCP);
 
136
        if (sock != -1)
 
137
        {
 
138
            const int val = 1;
 
139
 
 
140
            setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof (val));
 
141
#ifdef AF_INET6
 
142
            if (ss.ss_family == AF_INET6)
 
143
                setsockopt (sock, IPPROTO_IPV6, IPV6_V6ONLY, &val, sizeof (val));
 
144
#endif
 
145
            if (bind (sock, (struct sockaddr *)&ss, len) == 0)
 
146
            {
 
147
                send_fd (fd, sock);
 
148
                close (sock);
 
149
                continue;
 
150
            }
 
151
        }
 
152
        send_err (fd, errno);
 
153
    }
 
154
}
 
155
 
 
156
/* TODO?
 
157
 *  - use libcap if available,
 
158
 *  - call chroot
 
159
 */
 
160
 
 
161
int main (int argc, char *argv[])
 
162
{
 
163
    /* Support for dynamically opening RTSP, HTTP and HTTP/SSL ports */
 
164
    int pair[2];
 
165
 
 
166
    if (socketpair (AF_LOCAL, SOCK_STREAM, 0, pair))
 
167
        return 1;
 
168
    if (pair[0] < 3)
 
169
        goto error; /* we want 0, 1 and 2 open */
 
170
 
 
171
    pid_t pid = fork ();
 
172
    switch (pid)
 
173
    {
 
174
        case -1:
 
175
            goto error;
 
176
 
 
177
        case 0:
 
178
        {
 
179
            int null = open ("/dev/null", O_RDWR);
 
180
            if (null != -1)
 
181
            {
 
182
                dup2 (null, 0);
 
183
                dup2 (null, 1);
 
184
                dup2 (null, 2);
 
185
                close (null);
 
186
            }
 
187
            close (pair[0]);
 
188
            setsid ();
 
189
            rootprocess (pair[1]);
 
190
            exit (0);
 
191
        }
 
192
    }
 
193
 
 
194
    close (pair[1]);
 
195
    pair[1] = -1;
 
196
 
 
197
    char buf[21];
 
198
    snprintf (buf, sizeof (buf), "%d", pair[0]);
 
199
    setenv ("VLC_ROOTWRAP_SOCK", buf, 1);
 
200
 
 
201
    /* Support for real-time priorities */
 
202
#ifdef RLIMIT_RTPRIO
 
203
    struct rlimit rlim;
 
204
    rlim.rlim_max = rlim.rlim_cur = sched_get_priority_min (SCHED_RR) + 24;
 
205
    setrlimit (RLIMIT_RTPRIO, &rlim);
 
206
#endif
 
207
 
 
208
    uid_t uid = getuid ();
 
209
    if (uid == 0)
 
210
    {
 
211
        const char *sudo = getenv ("SUDO_UID");
 
212
        if (sudo)
 
213
            uid = atoi (sudo);
 
214
    }
 
215
    if (uid == 0)
 
216
    {
 
217
        fprintf (stderr, "Cannot determine unprivileged user for VLC!\n");
 
218
        exit (1);
 
219
    }
 
220
    setuid (uid);
 
221
 
 
222
    if (!setuid (0)) /* sanity check: we cannot get root back */
 
223
        exit (1);
 
224
 
 
225
    /* Yeah, the user can execute just about anything from here.
 
226
     * But we've dropped privileges, so it does not matter. */
 
227
    if (strlen (argv[0]) < sizeof ("-wrapper"))
 
228
        goto error;
 
229
    argv[0][strlen (argv[0]) - strlen ("-wrapper")] = '\0';
 
230
 
 
231
    (void)argc;
 
232
    if (execvp (argv[0], argv))
 
233
        perror (argv[0]);
 
234
 
 
235
error:
 
236
    close (pair[0]);
 
237
    if (pair[1] != -1)
 
238
        close (pair[1]);
 
239
    return 1;
 
240
}