main.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511
  1. /*
  2. * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
  3. * Copyright (c) 2021, Peter Elliott <pelliott@serenityos.org>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #include "Service.h"
  8. #include <AK/Assertions.h>
  9. #include <AK/ByteBuffer.h>
  10. #include <AK/Debug.h>
  11. #include <Kernel/API/DeviceEvent.h>
  12. #include <LibCore/ArgsParser.h>
  13. #include <LibCore/ConfigFile.h>
  14. #include <LibCore/DirIterator.h>
  15. #include <LibCore/Event.h>
  16. #include <LibCore/EventLoop.h>
  17. #include <LibCore/File.h>
  18. #include <LibCore/System.h>
  19. #include <LibMain/Main.h>
  20. #include <errno.h>
  21. #include <fcntl.h>
  22. #include <grp.h>
  23. #include <signal.h>
  24. #include <stdio.h>
  25. #include <sys/stat.h>
  26. #include <sys/sysmacros.h>
  27. #include <sys/types.h>
  28. #include <sys/wait.h>
  29. #include <unistd.h>
  30. String g_system_mode = "graphical";
  31. static void sigchld_handler(int)
  32. {
  33. for (;;) {
  34. int status = 0;
  35. pid_t pid = waitpid(-1, &status, WNOHANG);
  36. if (pid < 0) {
  37. perror("waitpid");
  38. break;
  39. }
  40. if (pid == 0)
  41. break;
  42. dbgln_if(SYSTEMSERVER_DEBUG, "Reaped child with pid {}, exit status {}", pid, status);
  43. Service* service = Service::find_by_pid(pid);
  44. if (service == nullptr) {
  45. // This can happen for multi-instance services.
  46. continue;
  47. }
  48. service->did_exit(status);
  49. }
  50. }
  51. static ErrorOr<void> determine_system_mode()
  52. {
  53. auto f = Core::File::construct("/proc/system_mode");
  54. if (!f->open(Core::OpenMode::ReadOnly)) {
  55. dbgln("Failed to read system_mode: {}", f->error_string());
  56. // Continue to assume "graphical".
  57. return {};
  58. }
  59. const String system_mode = String::copy(f->read_all(), Chomp);
  60. if (f->error()) {
  61. dbgln("Failed to read system_mode: {}", f->error_string());
  62. // Continue to assume "graphical".
  63. return {};
  64. }
  65. g_system_mode = system_mode;
  66. dbgln("Read system_mode: {}", g_system_mode);
  67. // FIXME: Support more than one framebuffer detection
  68. struct stat file_state;
  69. int rc = lstat("/dev/fb0", &file_state);
  70. if (rc == 0 && g_system_mode == "text") {
  71. dbgln("WARNING: Text mode with framebuffers won't work as expected! Consider using 'fbdev=off'.");
  72. }
  73. dbgln("System in {} mode", g_system_mode);
  74. return {};
  75. }
  76. static void chown_wrapper(char const* path, uid_t uid, gid_t gid)
  77. {
  78. int rc = chown(path, uid, gid);
  79. if (rc < 0 && errno != ENOENT) {
  80. VERIFY_NOT_REACHED();
  81. }
  82. }
  83. static void chmod_wrapper(char const* path, mode_t mode)
  84. {
  85. int rc = chmod(path, mode);
  86. if (rc < 0 && errno != ENOENT) {
  87. VERIFY_NOT_REACHED();
  88. }
  89. }
  90. static void chown_all_matching_device_nodes_under_specific_directory(StringView directory, group* group)
  91. {
  92. VERIFY(group);
  93. struct stat cur_file_stat;
  94. Core::DirIterator di(directory, Core::DirIterator::SkipParentAndBaseDir);
  95. if (di.has_error())
  96. VERIFY_NOT_REACHED();
  97. while (di.has_next()) {
  98. auto entry_name = di.next_full_path();
  99. auto rc = stat(entry_name.characters(), &cur_file_stat);
  100. if (rc < 0)
  101. continue;
  102. chown_wrapper(entry_name.characters(), 0, group->gr_gid);
  103. }
  104. }
  105. static void chown_all_matching_device_nodes(group* group, unsigned major_number)
  106. {
  107. VERIFY(group);
  108. struct stat cur_file_stat;
  109. Core::DirIterator di("/dev/", Core::DirIterator::SkipParentAndBaseDir);
  110. if (di.has_error())
  111. VERIFY_NOT_REACHED();
  112. while (di.has_next()) {
  113. auto entry_name = di.next_full_path();
  114. auto rc = stat(entry_name.characters(), &cur_file_stat);
  115. if (rc < 0)
  116. continue;
  117. if (major(cur_file_stat.st_rdev) != major_number)
  118. continue;
  119. chown_wrapper(entry_name.characters(), 0, group->gr_gid);
  120. }
  121. }
  122. inline char offset_character_with_number(char base_char, u8 offset)
  123. {
  124. char offsetted_char = base_char;
  125. VERIFY(static_cast<size_t>(offsetted_char) + static_cast<size_t>(offset) < 256);
  126. offsetted_char += offset;
  127. return offsetted_char;
  128. }
  129. static void create_devtmpfs_block_device(String name, mode_t mode, unsigned major, unsigned minor)
  130. {
  131. if (auto rc = mknod(name.characters(), mode | S_IFBLK, makedev(major, minor)); rc < 0)
  132. VERIFY_NOT_REACHED();
  133. }
  134. static void create_devtmpfs_char_device(String name, mode_t mode, unsigned major, unsigned minor)
  135. {
  136. if (auto rc = mknod(name.characters(), mode | S_IFCHR, makedev(major, minor)); rc < 0)
  137. VERIFY_NOT_REACHED();
  138. }
  139. static void populate_devtmpfs_char_devices_based_on_sysfs()
  140. {
  141. Core::DirIterator di("/sys/dev/char/", Core::DirIterator::SkipParentAndBaseDir);
  142. if (di.has_error()) {
  143. warnln("Failed to open /sys/dev/char - {}", di.error());
  144. VERIFY_NOT_REACHED();
  145. }
  146. while (di.has_next()) {
  147. auto entry_name = di.next_path().split(':');
  148. VERIFY(entry_name.size() == 2);
  149. auto major_number = entry_name[0].to_uint<unsigned>().value();
  150. auto minor_number = entry_name[1].to_uint<unsigned>().value();
  151. switch (major_number) {
  152. case 2: {
  153. switch (minor_number) {
  154. case 10: {
  155. create_devtmpfs_char_device("/dev/devctl", 0660, 2, 10);
  156. break;
  157. }
  158. default:
  159. warnln("Unknown character device {}:{}", major_number, minor_number);
  160. }
  161. break;
  162. }
  163. default:
  164. break;
  165. }
  166. }
  167. }
  168. static void populate_devtmpfs_devices_based_on_devctl()
  169. {
  170. auto f = Core::File::construct("/dev/devctl");
  171. if (!f->open(Core::OpenMode::ReadOnly)) {
  172. warnln("Failed to open /dev/devctl - {}", f->error_string());
  173. VERIFY_NOT_REACHED();
  174. }
  175. DeviceEvent event;
  176. while (f->read((u8*)&event, sizeof(DeviceEvent)) > 0) {
  177. if (event.state != DeviceEvent::Inserted)
  178. continue;
  179. auto major_number = event.major_number;
  180. auto minor_number = event.minor_number;
  181. bool is_block_device = (event.is_block_device == 1);
  182. switch (major_number) {
  183. case 116: {
  184. if (!is_block_device) {
  185. create_devtmpfs_char_device(String::formatted("/dev/audio/{}", minor_number), 0220, 116, minor_number);
  186. break;
  187. }
  188. break;
  189. }
  190. case 28: {
  191. create_devtmpfs_block_device(String::formatted("/dev/gpu{}", minor_number), 0666, 28, minor_number);
  192. break;
  193. }
  194. case 29: {
  195. if (is_block_device) {
  196. create_devtmpfs_block_device(String::formatted("/dev/fb{}", minor_number), 0666, 29, minor_number);
  197. break;
  198. }
  199. switch (minor_number) {
  200. case 0: {
  201. create_devtmpfs_char_device("/dev/full", 0660, 29, 0);
  202. break;
  203. }
  204. default:
  205. warnln("Unknown character device {}:{}", major_number, minor_number);
  206. }
  207. break;
  208. }
  209. case 229: {
  210. if (!is_block_device) {
  211. create_devtmpfs_char_device(String::formatted("/dev/hvc0p{}", minor_number), 0666, major_number, minor_number);
  212. }
  213. break;
  214. }
  215. case 10: {
  216. if (!is_block_device) {
  217. switch (minor_number) {
  218. case 0: {
  219. create_devtmpfs_char_device("/dev/mouse0", 0660, 10, 0);
  220. break;
  221. }
  222. case 183: {
  223. create_devtmpfs_char_device("/dev/hwrng", 0660, 10, 183);
  224. break;
  225. }
  226. default:
  227. warnln("Unknown character device {}:{}", major_number, minor_number);
  228. }
  229. }
  230. break;
  231. }
  232. case 85: {
  233. if (!is_block_device) {
  234. switch (minor_number) {
  235. case 0: {
  236. create_devtmpfs_char_device("/dev/keyboard0", 0660, 85, 0);
  237. break;
  238. }
  239. default:
  240. warnln("Unknown character device {}:{}", major_number, minor_number);
  241. }
  242. }
  243. break;
  244. }
  245. case 1: {
  246. if (!is_block_device) {
  247. switch (minor_number) {
  248. case 5: {
  249. create_devtmpfs_char_device("/dev/zero", 0666, 1, 5);
  250. break;
  251. }
  252. case 1: {
  253. create_devtmpfs_char_device("/dev/mem", 0660, 1, 1);
  254. break;
  255. }
  256. case 3: {
  257. create_devtmpfs_char_device("/dev/null", 0666, 1, 3);
  258. break;
  259. }
  260. case 8: {
  261. create_devtmpfs_char_device("/dev/random", 0666, 1, 8);
  262. break;
  263. }
  264. default:
  265. warnln("Unknown character device {}:{}", major_number, minor_number);
  266. break;
  267. }
  268. }
  269. break;
  270. }
  271. case 30: {
  272. if (is_block_device) {
  273. create_devtmpfs_block_device(String::formatted("/dev/kcov{}", minor_number), 0666, 30, minor_number);
  274. }
  275. break;
  276. }
  277. case 3: {
  278. if (is_block_device) {
  279. create_devtmpfs_block_device(String::formatted("/dev/hd{}", offset_character_with_number('a', minor_number)), 0600, 3, minor_number);
  280. }
  281. break;
  282. }
  283. case 5: {
  284. if (!is_block_device) {
  285. switch (minor_number) {
  286. case 1: {
  287. create_devtmpfs_char_device("/dev/console", 0666, 5, 1);
  288. break;
  289. }
  290. case 2: {
  291. create_devtmpfs_char_device("/dev/ptmx", 0666, 5, 2);
  292. break;
  293. }
  294. case 0: {
  295. create_devtmpfs_char_device("/dev/tty", 0666, 5, 0);
  296. break;
  297. }
  298. default:
  299. warnln("Unknown character device {}:{}", major_number, minor_number);
  300. }
  301. }
  302. break;
  303. }
  304. case 4: {
  305. if (!is_block_device) {
  306. switch (minor_number) {
  307. case 0: {
  308. create_devtmpfs_char_device("/dev/tty0", 0620, 4, 0);
  309. break;
  310. }
  311. case 1: {
  312. create_devtmpfs_char_device("/dev/tty1", 0620, 4, 1);
  313. break;
  314. }
  315. case 2: {
  316. create_devtmpfs_char_device("/dev/tty2", 0620, 4, 2);
  317. break;
  318. }
  319. case 3: {
  320. create_devtmpfs_char_device("/dev/tty3", 0620, 4, 3);
  321. break;
  322. }
  323. case 64: {
  324. create_devtmpfs_char_device("/dev/ttyS0", 0620, 4, 64);
  325. break;
  326. }
  327. case 65: {
  328. create_devtmpfs_char_device("/dev/ttyS1", 0620, 4, 65);
  329. break;
  330. }
  331. case 66: {
  332. create_devtmpfs_char_device("/dev/ttyS2", 0620, 4, 66);
  333. break;
  334. }
  335. case 67: {
  336. create_devtmpfs_char_device("/dev/ttyS3", 0666, 4, 67);
  337. break;
  338. }
  339. default:
  340. warnln("Unknown character device {}:{}", major_number, minor_number);
  341. }
  342. }
  343. break;
  344. }
  345. default:
  346. if (!is_block_device)
  347. warnln("Unknown character device {}:{}", major_number, minor_number);
  348. else
  349. warnln("Unknown block device {}:{}", major_number, minor_number);
  350. break;
  351. }
  352. }
  353. }
  354. static void populate_devtmpfs()
  355. {
  356. mode_t old_mask = umask(0);
  357. printf("Changing umask %#o\n", old_mask);
  358. populate_devtmpfs_char_devices_based_on_sysfs();
  359. populate_devtmpfs_devices_based_on_devctl();
  360. umask(old_mask);
  361. }
  362. static ErrorOr<void> prepare_synthetic_filesystems()
  363. {
  364. // FIXME: Find a better way to all of this stuff, without hardcoding all of this!
  365. TRY(Core::System::mount(-1, "/proc", "proc", MS_NOSUID));
  366. TRY(Core::System::mount(-1, "/sys", "sys", 0));
  367. TRY(Core::System::mount(-1, "/dev", "dev", 0));
  368. TRY(Core::System::mkdir("/dev/audio", 0755));
  369. TRY(Core::System::symlink("/proc/self/fd/0", "/dev/stdin"));
  370. TRY(Core::System::symlink("/proc/self/fd/1", "/dev/stdout"));
  371. TRY(Core::System::symlink("/proc/self/fd/2", "/dev/stderr"));
  372. populate_devtmpfs();
  373. TRY(Core::System::mkdir("/dev/pts", 0755));
  374. TRY(Core::System::mount(-1, "/dev/pts", "devpts", 0));
  375. TRY(Core::System::symlink("/dev/random", "/dev/urandom"));
  376. chmod_wrapper("/dev/urandom", 0666);
  377. auto phys_group = getgrnam("phys");
  378. VERIFY(phys_group);
  379. // FIXME: Try to find a way to not hardcode the major number of framebuffer device nodes.
  380. chown_all_matching_device_nodes(phys_group, 29);
  381. chown_wrapper("/dev/keyboard0", 0, phys_group->gr_gid);
  382. chown_wrapper("/dev/mouse0", 0, phys_group->gr_gid);
  383. auto tty_group = getgrnam("tty");
  384. VERIFY(tty_group);
  385. // FIXME: Try to find a way to not hardcode the major number of tty nodes.
  386. chown_all_matching_device_nodes(tty_group, 4);
  387. auto audio_group = getgrnam("audio");
  388. VERIFY(audio_group);
  389. chown_wrapper("/dev/audio", 0, audio_group->gr_gid);
  390. chown_all_matching_device_nodes_under_specific_directory("/dev/audio", audio_group);
  391. // Note: We open the /dev/null device and set file descriptors 0, 1, 2 to it
  392. // because otherwise these file descriptors won't have a custody, making
  393. // the ProcFS file descriptor links (at /proc/PID/fd/{0,1,2}) to have an
  394. // absolute path of "device:1,3" instead of something like "/dev/null".
  395. // This affects also every other process that inherits the file descriptors
  396. // from SystemServer, so it is important for other things (also for ProcFS
  397. // tests that are running in CI mode).
  398. int stdin_new_fd = TRY(Core::System::open("/dev/null", O_NONBLOCK));
  399. TRY(Core::System::dup2(stdin_new_fd, 0));
  400. TRY(Core::System::dup2(stdin_new_fd, 1));
  401. TRY(Core::System::dup2(stdin_new_fd, 2));
  402. endgrent();
  403. return {};
  404. }
  405. static ErrorOr<void> mount_all_filesystems()
  406. {
  407. dbgln("Spawning mount -a to mount all filesystems.");
  408. pid_t pid = TRY(Core::System::fork());
  409. if (pid == 0) {
  410. execl("/bin/mount", "mount", "-a", nullptr);
  411. perror("exec");
  412. VERIFY_NOT_REACHED();
  413. } else {
  414. wait(nullptr);
  415. }
  416. return {};
  417. }
  418. static ErrorOr<void> create_tmp_coredump_directory()
  419. {
  420. dbgln("Creating /tmp/coredump directory");
  421. auto old_umask = umask(0);
  422. // FIXME: the coredump directory should be made read-only once CrashDaemon is no longer responsible for compressing coredumps
  423. TRY(Core::System::mkdir("/tmp/coredump", 0777));
  424. umask(old_umask);
  425. return {};
  426. }
  427. ErrorOr<int> serenity_main(Main::Arguments arguments)
  428. {
  429. bool user = false;
  430. Core::ArgsParser args_parser;
  431. args_parser.add_option(user, "Run in user-mode", "user", 'u');
  432. args_parser.parse(arguments);
  433. if (!user) {
  434. TRY(mount_all_filesystems());
  435. TRY(prepare_synthetic_filesystems());
  436. }
  437. TRY(Core::System::pledge("stdio proc exec tty accept unix rpath wpath cpath chown fattr id sigaction"));
  438. if (!user) {
  439. TRY(create_tmp_coredump_directory());
  440. TRY(determine_system_mode());
  441. }
  442. Core::EventLoop event_loop;
  443. event_loop.register_signal(SIGCHLD, sigchld_handler);
  444. // Read our config and instantiate services.
  445. // This takes care of setting up sockets.
  446. NonnullRefPtrVector<Service> services;
  447. auto config = (user)
  448. ? TRY(Core::ConfigFile::open_for_app("SystemServer"))
  449. : TRY(Core::ConfigFile::open_for_system("SystemServer"));
  450. for (auto name : config->groups()) {
  451. auto service = Service::construct(*config, name);
  452. if (service->is_enabled())
  453. services.append(service);
  454. }
  455. // After we've set them all up, activate them!
  456. dbgln("Activating {} services...", services.size());
  457. for (auto& service : services)
  458. service.activate();
  459. return event_loop.exec();
  460. }