~ubuntu-branches/ubuntu/trusty/systemd/trusty

« back to all changes in this revision

Viewing changes to src/core/execute.c

Tags: upstream-202
ImportĀ upstreamĀ versionĀ 202

Show diffs side-by-side

added added

removed removed

Lines of Context:
40
40
#include <sys/poll.h>
41
41
#include <linux/seccomp-bpf.h>
42
42
#include <glob.h>
 
43
#include <libgen.h>
43
44
 
44
45
#ifdef HAVE_PAM
45
46
#include <security/pam_appl.h>
173
174
                o == EXEC_OUTPUT_JOURNAL_AND_CONSOLE;
174
175
}
175
176
 
 
177
void exec_context_serialize(const ExecContext *context, Unit *u, FILE *f) {
 
178
        assert(context);
 
179
        assert(u);
 
180
        assert(f);
 
181
 
 
182
        if (context->tmp_dir)
 
183
                unit_serialize_item(u, f, "tmp-dir", context->tmp_dir);
 
184
 
 
185
        if (context->var_tmp_dir)
 
186
                unit_serialize_item(u, f, "var-tmp-dir", context->var_tmp_dir);
 
187
}
 
188
 
176
189
static int open_null_as(int flags, int nfd) {
177
190
        int fd, r;
178
191
 
192
205
 
193
206
static int connect_logger_as(const ExecContext *context, ExecOutput output, const char *ident, const char *unit_id, int nfd) {
194
207
        int fd, r;
195
 
        union sockaddr_union sa;
 
208
        union sockaddr_union sa = {
 
209
                .un.sun_family = AF_UNIX,
 
210
                .un.sun_path = "/run/systemd/journal/stdout",
 
211
        };
196
212
 
197
213
        assert(context);
198
214
        assert(output < _EXEC_OUTPUT_MAX);
203
219
        if (fd < 0)
204
220
                return -errno;
205
221
 
206
 
        zero(sa);
207
 
        sa.un.sun_family = AF_UNIX;
208
 
        strncpy(sa.un.sun_path, "/run/systemd/journal/stdout", sizeof(sa.un.sun_path));
209
 
 
210
222
        r = connect(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path));
211
223
        if (r < 0) {
212
224
                close_nointr_nofail(fd);
658
670
 
659
671
                /* First step: If we need to keep capabilities but
660
672
                 * drop privileges we need to make sure we keep our
661
 
                 * caps, whiel we drop privileges. */
 
673
                 * caps, while we drop privileges. */
662
674
                if (uid != 0) {
663
 
                        int sb = context->secure_bits|SECURE_KEEP_CAPS;
 
675
                        int sb = context->secure_bits | 1<<SECURE_KEEP_CAPS;
664
676
 
665
677
                        if (prctl(PR_GET_SECUREBITS) != sb)
666
678
                                if (prctl(PR_SET_SECUREBITS, sb) < 0)
925
937
        int i;
926
938
        unsigned n;
927
939
        struct sock_filter *f;
928
 
        struct sock_fprog prog;
 
940
        struct sock_fprog prog = {};
929
941
 
930
942
        assert(syscall_filter);
931
943
 
957
969
        memcpy(f + (ELEMENTSOF(header) + 2*n), footer, sizeof(footer));
958
970
 
959
971
        /* Third: install the filter */
960
 
        zero(prog);
961
972
        prog.len = ELEMENTSOF(header) + ELEMENTSOF(footer) + 2*n;
962
973
        prog.filter = f;
963
974
        if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) < 0)
968
979
 
969
980
int exec_spawn(ExecCommand *command,
970
981
               char **argv,
971
 
               const ExecContext *context,
 
982
               ExecContext *context,
972
983
               int fds[], unsigned n_fds,
973
984
               char **environment,
974
985
               bool apply_permissions,
986
997
        int r;
987
998
        char *line;
988
999
        int socket_fd;
989
 
        char _cleanup_strv_free_ **files_env = NULL;
 
1000
        _cleanup_strv_free_ char **files_env = NULL;
990
1001
 
991
1002
        assert(command);
992
1003
        assert(context);
1025
1036
                return log_oom();
1026
1037
 
1027
1038
        log_struct_unit(LOG_DEBUG,
1028
 
                   unit_id,
1029
 
                   "MESSAGE=About to execute %s", line,
1030
 
                   NULL);
 
1039
                        unit_id,
 
1040
                        "EXECUTABLE=%s", command->path,
 
1041
                        "MESSAGE=About to execute: %s", line,
 
1042
                        NULL);
1031
1043
        free(line);
1032
1044
 
1033
1045
        r = cgroup_bonding_realize_list(cgroup_bondings);
1034
1046
        if (r < 0)
1035
1047
                return r;
1036
1048
 
 
1049
        /* We must initialize the attributes in the parent, before we
 
1050
        fork, because we really need them initialized before making
 
1051
        the process a member of the group (which we do in both the
 
1052
        child and the parent), and we cannot really apply them twice
 
1053
        (due to 'append' style attributes) */
1037
1054
        cgroup_attribute_apply_list(cgroup_attributes, cgroup_bondings);
1038
1055
 
 
1056
        if (context->private_tmp && !context->tmp_dir && !context->var_tmp_dir) {
 
1057
                r = setup_tmpdirs(&context->tmp_dir, &context->var_tmp_dir);
 
1058
                if (r < 0)
 
1059
                        return r;
 
1060
        }
 
1061
 
1039
1062
        pid = fork();
1040
1063
        if (pid < 0)
1041
1064
                return -errno;
1046
1069
                const char *username = NULL, *home = NULL;
1047
1070
                uid_t uid = (uid_t) -1;
1048
1071
                gid_t gid = (gid_t) -1;
1049
 
                char _cleanup_strv_free_ **our_env = NULL, **pam_env = NULL,
 
1072
                _cleanup_strv_free_ char **our_env = NULL, **pam_env = NULL,
1050
1073
                        **final_env = NULL, **final_argv = NULL;
1051
1074
                unsigned n_env = 0;
1052
1075
                bool set_access = false;
1176
1199
                        snprintf(t, sizeof(t), "%i", context->oom_score_adjust);
1177
1200
                        char_array_0(t);
1178
1201
 
1179
 
                        if (write_one_line_file("/proc/self/oom_score_adj", t) < 0) {
 
1202
                        if (write_string_file("/proc/self/oom_score_adj", t) < 0) {
1180
1203
                                err = -errno;
1181
1204
                                r = EXIT_OOM_ADJUST;
1182
1205
                                goto fail_child;
1191
1214
                        }
1192
1215
 
1193
1216
                if (context->cpu_sched_set) {
1194
 
                        struct sched_param param;
1195
 
 
1196
 
                        zero(param);
1197
 
                        param.sched_priority = context->cpu_sched_priority;
1198
 
 
1199
 
                        if (sched_setscheduler(0, context->cpu_sched_policy |
1200
 
                                               (context->cpu_sched_reset_on_fork ? SCHED_RESET_ON_FORK : 0), &param) < 0) {
 
1217
                        struct sched_param param = {
 
1218
                                .sched_priority = context->cpu_sched_priority,
 
1219
                        };
 
1220
 
 
1221
                        r = sched_setscheduler(0,
 
1222
                                               context->cpu_sched_policy |
 
1223
                                               (context->cpu_sched_reset_on_fork ?
 
1224
                                                SCHED_RESET_ON_FORK : 0),
 
1225
                                               &param);
 
1226
                        if (r < 0) {
1201
1227
                                err = -errno;
1202
1228
                                r = EXIT_SETSCHEDULER;
1203
1229
                                goto fail_child;
1247
1273
                        if (cgroup_bondings && context->control_group_modify) {
1248
1274
                                err = cgroup_bonding_set_group_access_list(cgroup_bondings, 0755, uid, gid);
1249
1275
                                if (err >= 0)
1250
 
                                        err = cgroup_bonding_set_task_access_list(cgroup_bondings, 0644, uid, gid, context->control_group_persistent);
 
1276
                                        err = cgroup_bonding_set_task_access_list(
 
1277
                                                        cgroup_bondings,
 
1278
                                                        0644,
 
1279
                                                        uid,
 
1280
                                                        gid,
 
1281
                                                        context->control_group_persistent);
1251
1282
                                if (err < 0) {
1252
1283
                                        r = EXIT_CGROUP;
1253
1284
                                        goto fail_child;
1258
1289
                }
1259
1290
 
1260
1291
                if (cgroup_bondings && !set_access && context->control_group_persistent >= 0)  {
1261
 
                        err = cgroup_bonding_set_task_access_list(cgroup_bondings, (mode_t) -1, (uid_t) -1, (uid_t) -1, context->control_group_persistent);
 
1292
                        err = cgroup_bonding_set_task_access_list(
 
1293
                                        cgroup_bondings,
 
1294
                                        (mode_t) -1,
 
1295
                                        (uid_t) -1,
 
1296
                                        (uid_t) -1,
 
1297
                                        context->control_group_persistent);
1262
1298
                        if (err < 0) {
1263
1299
                                r = EXIT_CGROUP;
1264
1300
                                goto fail_child;
1302
1338
                        err = setup_namespace(context->read_write_dirs,
1303
1339
                                              context->read_only_dirs,
1304
1340
                                              context->inaccessible_dirs,
 
1341
                                              context->tmp_dir,
 
1342
                                              context->var_tmp_dir,
1305
1343
                                              context->private_tmp,
1306
1344
                                              context->mount_flags);
1307
1345
                        if (err < 0) {
1324
1362
                                goto fail_child;
1325
1363
                        }
1326
1364
                } else {
1327
 
                        char _cleanup_free_ *d = NULL;
 
1365
                        _cleanup_free_ char *d = NULL;
1328
1366
 
1329
1367
                        if (asprintf(&d, "%s/%s",
1330
1368
                                     context->root_directory ? context->root_directory : "",
1416
1454
                        }
1417
1455
                }
1418
1456
 
1419
 
                if (!(our_env = new0(char*, 7))) {
 
1457
                our_env = new0(char*, 7);
 
1458
                if (!our_env) {
1420
1459
                        err = -ENOMEM;
1421
1460
                        r = EXIT_MEMORY;
1422
1461
                        goto fail_child;
1456
1495
 
1457
1496
                assert(n_env <= 7);
1458
1497
 
1459
 
                if (!(final_env = strv_env_merge(
1460
 
                                      5,
1461
 
                                      environment,
1462
 
                                      our_env,
1463
 
                                      context->environment,
1464
 
                                      files_env,
1465
 
                                      pam_env,
1466
 
                                      NULL))) {
 
1498
                final_env = strv_env_merge(5,
 
1499
                                           environment,
 
1500
                                           our_env,
 
1501
                                           context->environment,
 
1502
                                           files_env,
 
1503
                                           pam_env,
 
1504
                                           NULL);
 
1505
                if (!final_env) {
1467
1506
                        err = -ENOMEM;
1468
1507
                        r = EXIT_MEMORY;
1469
1508
                        goto fail_child;
1470
1509
                }
1471
1510
 
1472
 
                if (!(final_argv = replace_env_argv(argv, final_env))) {
 
1511
                final_argv = replace_env_argv(argv, final_env);
 
1512
                if (!final_argv) {
1473
1513
                        err = -ENOMEM;
1474
1514
                        r = EXIT_MEMORY;
1475
1515
                        goto fail_child;
1477
1517
 
1478
1518
                final_env = strv_env_clean(final_env);
1479
1519
 
 
1520
                if (_unlikely_(log_get_max_level() >= LOG_PRI(LOG_DEBUG))) {
 
1521
                        line = exec_command_line(final_argv);
 
1522
                        if (line) {
 
1523
                                log_open();
 
1524
                                log_struct_unit(LOG_DEBUG,
 
1525
                                                unit_id,
 
1526
                                                "EXECUTABLE=%s", command->path,
 
1527
                                                "MESSAGE=Executing: %s", line,
 
1528
                                                NULL);
 
1529
                                log_close();
 
1530
                                free(line);
 
1531
                                line = NULL;
 
1532
                        }
 
1533
                }
1480
1534
                execve(command->path, final_argv, final_env);
1481
1535
                err = -errno;
1482
1536
                r = EXIT_EXEC;
1498
1552
        }
1499
1553
 
1500
1554
        log_struct_unit(LOG_DEBUG,
1501
 
                   unit_id,
1502
 
                   "MESSAGE=Forked %s as %lu",
1503
 
                          command->path, (unsigned long) pid,
1504
 
                   NULL);
 
1555
                        unit_id,
 
1556
                        "MESSAGE=Forked %s as %lu",
 
1557
                        command->path, (unsigned long) pid,
 
1558
                        NULL);
1505
1559
 
1506
1560
        /* We add the new process to the cgroup both in the child (so
1507
1561
         * that we can be sure that no user code is ever executed
1508
1562
         * outside of the cgroup) and in the parent (so that we can be
1509
1563
         * sure that when we kill the cgroup the process will be
1510
1564
         * killed too). */
1511
 
        if (cgroup_bondings)
1512
 
                cgroup_bonding_install_list(cgroup_bondings, pid, cgroup_suffix);
 
1565
        cgroup_bonding_install_list(cgroup_bondings, pid, cgroup_suffix);
1513
1566
 
1514
1567
        exec_status_start(&command->exec_status, pid);
1515
1568
 
1530
1583
        c->timer_slack_nsec = (nsec_t) -1;
1531
1584
}
1532
1585
 
1533
 
void exec_context_done(ExecContext *c) {
 
1586
void exec_context_tmp_dirs_done(ExecContext *c) {
 
1587
        char* dirs[] = {c->tmp_dir ? c->tmp_dir : c->var_tmp_dir,
 
1588
                        c->tmp_dir ? c->var_tmp_dir : NULL,
 
1589
                        NULL};
 
1590
        char **dirp;
 
1591
 
 
1592
        for(dirp = dirs; *dirp; dirp++) {
 
1593
                char *dir;
 
1594
                int r;
 
1595
 
 
1596
                r = rm_rf_dangerous(*dirp, false, true, false);
 
1597
                dir = dirname(*dirp);
 
1598
                if (r < 0)
 
1599
                        log_warning("Failed to remove content of temporary directory %s: %s",
 
1600
                                    dir, strerror(-r));
 
1601
                else {
 
1602
                        r = rmdir(dir);
 
1603
                        if (r < 0)
 
1604
                                log_warning("Failed to remove  temporary directory %s: %s",
 
1605
                                            dir, strerror(-r));
 
1606
                }
 
1607
 
 
1608
                free(*dirp);
 
1609
        }
 
1610
 
 
1611
        c->tmp_dir = c->var_tmp_dir = NULL;
 
1612
}
 
1613
 
 
1614
void exec_context_done(ExecContext *c, bool reloading_or_reexecuting) {
1534
1615
        unsigned l;
1535
1616
 
1536
1617
        assert(c);
1594
1675
 
1595
1676
        free(c->syscall_filter);
1596
1677
        c->syscall_filter = NULL;
 
1678
 
 
1679
        if (!reloading_or_reexecuting)
 
1680
                exec_context_tmp_dirs_done(c);
1597
1681
}
1598
1682
 
1599
1683
void exec_command_done(ExecCommand *c) {
1643
1727
                int k;
1644
1728
                bool ignore = false;
1645
1729
                char **p;
1646
 
                glob_t pglob;
 
1730
                _cleanup_globfree_ glob_t pglob = {};
1647
1731
                int count, n;
1648
1732
 
1649
1733
                fn = *i;
1654
1738
                }
1655
1739
 
1656
1740
                if (!path_is_absolute(fn)) {
1657
 
 
1658
1741
                        if (ignore)
1659
1742
                                continue;
1660
1743
 
1663
1746
                }
1664
1747
 
1665
1748
                /* Filename supports globbing, take all matching files */
1666
 
                zero(pglob);
1667
1749
                errno = 0;
1668
1750
                if (glob(fn, 0, NULL, &pglob) != 0) {
1669
 
                        globfree(&pglob);
1670
1751
                        if (ignore)
1671
1752
                                continue;
1672
1753
 
1675
1756
                }
1676
1757
                count = pglob.gl_pathc;
1677
1758
                if (count == 0) {
1678
 
                        globfree(&pglob);
1679
1759
                        if (ignore)
1680
1760
                                continue;
1681
1761
 
1683
1763
                        return -EINVAL;
1684
1764
                }
1685
1765
                for (n = 0; n < count; n++) {
1686
 
                        k = load_env_file(pglob.gl_pathv[n], &p);
 
1766
                        k = load_env_file(pglob.gl_pathv[n], NULL, &p);
1687
1767
                        if (k < 0) {
1688
1768
                                if (ignore)
1689
1769
                                        continue;
1690
1770
 
1691
1771
                                strv_free(r);
1692
 
                                globfree(&pglob);
1693
1772
                                return k;
1694
1773
                         }
 
1774
                        /* Log invalid environment variables with filename */
 
1775
                        if (p)
 
1776
                                p = strv_env_clean_log(p, pglob.gl_pathv[n]);
1695
1777
 
1696
1778
                        if (r == NULL)
1697
1779
                                r = p;
1701
1783
                                m = strv_env_merge(2, r, p);
1702
1784
                                strv_free(r);
1703
1785
                                strv_free(p);
1704
 
 
1705
 
                                if (!m) {
1706
 
                                        globfree(&pglob);
 
1786
                                if (!m)
1707
1787
                                        return -ENOMEM;
1708
 
                                }
1709
1788
 
1710
1789
                                r = m;
1711
1790
                        }
1712
1791
                }
1713
 
                globfree(&pglob);
1714
1792
        }
1715
1793
 
1716
1794
        *l = r;
1911
1989
        if (c->secure_bits)
1912
1990
                fprintf(f, "%sSecure Bits:%s%s%s%s%s%s\n",
1913
1991
                        prefix,
1914
 
                        (c->secure_bits & SECURE_KEEP_CAPS) ? " keep-caps" : "",
1915
 
                        (c->secure_bits & SECURE_KEEP_CAPS_LOCKED) ? " keep-caps-locked" : "",
1916
 
                        (c->secure_bits & SECURE_NO_SETUID_FIXUP) ? " no-setuid-fixup" : "",
1917
 
                        (c->secure_bits & SECURE_NO_SETUID_FIXUP_LOCKED) ? " no-setuid-fixup-locked" : "",
1918
 
                        (c->secure_bits & SECURE_NOROOT) ? " noroot" : "",
1919
 
                        (c->secure_bits & SECURE_NOROOT_LOCKED) ? "noroot-locked" : "");
 
1992
                        (c->secure_bits & 1<<SECURE_KEEP_CAPS) ? " keep-caps" : "",
 
1993
                        (c->secure_bits & 1<<SECURE_KEEP_CAPS_LOCKED) ? " keep-caps-locked" : "",
 
1994
                        (c->secure_bits & 1<<SECURE_NO_SETUID_FIXUP) ? " no-setuid-fixup" : "",
 
1995
                        (c->secure_bits & 1<<SECURE_NO_SETUID_FIXUP_LOCKED) ? " no-setuid-fixup-locked" : "",
 
1996
                        (c->secure_bits & 1<<SECURE_NOROOT) ? " noroot" : "",
 
1997
                        (c->secure_bits & 1<<SECURE_NOROOT_LOCKED) ? "noroot-locked" : "");
1920
1998
 
1921
1999
        if (c->capability_bounding_set_drop) {
1922
2000
                unsigned long l;