|
|
| version 1.19, 2025/04/10 01:24:38 | version 1.23, 2025/04/16 05:33:15 |
|---|---|
| Line 24 | Line 24 |
| * along with FreeM. If not, see <https://www.gnu.org/licenses/>. | * along with FreeM. If not, see <https://www.gnu.org/licenses/>. |
| * | * |
| * $Log$ | * $Log$ |
| * Revision 1.23 2025/04/16 05:33:15 snw | |
| * Try to use procctl function to fix ASLR problem on FreeBSD | |
| * | |
| * Revision 1.22 2025/04/15 16:49:36 snw | |
| * Make use of logprintf throughout codebase | |
| * | |
| * Revision 1.21 2025/04/15 02:24:43 snw | |
| * Improve FreeM logging capabilities | |
| * | |
| * Revision 1.20 2025/04/13 04:22:43 snw | |
| * Fix snprintf calls | |
| * | |
| * Revision 1.19 2025/04/10 01:24:38 snw | * Revision 1.19 2025/04/10 01:24:38 snw |
| * Remove C++ style comments | * Remove C++ style comments |
| * | * |
| Line 106 | Line 118 |
| #include <errno.h> | #include <errno.h> |
| #include <pwd.h> | #include <pwd.h> |
| #include <grp.h> | #include <grp.h> |
| #include "log.h" | |
| #if defined(__FreeBSD__) | |
| # include <sys/procctl.h> | |
| #endif | |
| #if defined(HAVE_GETOPT_H) | #if defined(HAVE_GETOPT_H) |
| # include <getopt.h> | # include <getopt.h> |
| #endif | #endif |
| Line 121 extern char *getenv(const char *name); | Line 135 extern char *getenv(const char *name); |
| void freem_usage(void); | void freem_usage(void); |
| void freem_print_version(void); | void freem_print_version(void); |
| void init_ztrap(void); | void init_ztrap(void); |
| void m_log (int, const char *); | |
| int main (int argc, char **argv, char **envp) | int main (int argc, char **argv, char **envp) |
| { | { |
| Line 184 int main (int argc, char **argv, char ** | Line 197 int main (int argc, char **argv, char ** |
| char cli_rtn_name[256]; | char cli_rtn_name[256]; |
| char env_ena[25]; | char env_ena[25]; |
| #if defined(__FreeBSD__) | |
| int prcdta = PROC_ASLR_FORCE_DISABLE; | |
| if (procctl (P_PID, getpid (), PROC_ASLR_CTL, &prcdta) == -1) { | |
| fprintf (stderr, "freem: could not disable address space layout randomization for pid %ld; program operation may be unreliable [error %s]\n", getpid(), strerror (errno)); | |
| } | |
| #endif | |
| routine_mode = FALSE; | routine_mode = FALSE; |
| strcpy (m_dialect, "FREEM"); | strcpy (m_dialect, "FREEM"); |
| Line 459 int main (int argc, char **argv, char ** | Line 479 int main (int argc, char **argv, char ** |
| } | } |
| #endif | #endif |
| snprintf (config_file, 4096, "%s/freem/%s/freem.conf", SYSCONFDIR, shm_env); | snprintf (config_file, sizeof (config_file) - 1, "%s/freem/%s/freem.conf", SYSCONFDIR, shm_env); |
| snprintf (env_config_file, 4096, "%s/freem/env.conf", SYSCONFDIR); | snprintf (env_config_file, sizeof (config_file) - 1, "%s/freem/env.conf", SYSCONFDIR); |
| if (!file_exists (env_config_file)) { | if (!file_exists (env_config_file)) { |
| fprintf (stderr, "freem: environment catalog does not exist; may need to run fmadm configure\n"); | logprintf (FM_LOG_FATAL, "freem: environment catalog does not exist; may need to run fmadm configure"); |
| exit (1); | |
| } | } |
| if (!file_exists (config_file)) { | if (!file_exists (config_file)) { |
| fprintf (stderr, "freem: configuration file for %s does not exist; may need to run fmadm configure\n", shm_env); | logprintf (FM_LOG_FATAL, "freem: configuration file for %s does not exist; may need to run fmadm configure", shm_env); |
| exit (1); | |
| } | } |
| if (read_profile_string (env_config_file, shm_env, "user", d_username) == FALSE) { | if (read_profile_string (env_config_file, shm_env, "user", d_username) == FALSE) { |
| fprintf (stderr, "freem: could not determine owning user for environment %s\n", shm_env); | logprintf (FM_LOG_FATAL, "freem: could not determine owning user for environment %s", shm_env); |
| exit (1); | |
| } | } |
| if (read_profile_string (env_config_file, shm_env, "group", d_groupname) == FALSE) { | if (read_profile_string (env_config_file, shm_env, "group", d_groupname) == FALSE) { |
| fprintf (stderr, "freem: could not determine owning group for environment %s\n", shm_env); | logprintf (FM_LOG_FATAL, "freem: could not determine owning group for environment %s", shm_env); |
| exit (1); | |
| } | } |
| if (read_profile_string (env_config_file, shm_env, "enabled", env_ena) == FALSE) { | if (read_profile_string (env_config_file, shm_env, "enabled", env_ena) == FALSE) { |
| fprintf (stderr, "freem: could not discover enabled state for environment %s\n", shm_env); | logprintf (FM_LOG_FATAL, "freem: could not discover enabled state for environment %s", shm_env); |
| exit (1); | |
| } | } |
| if (strcmp (env_ena, "true") != 0) { | if (strcmp (env_ena, "true") != 0) { |
| fprintf (stderr, "freem: environment %s is administratively disabled\n", shm_env); | logprintf (FM_LOG_FATAL, "freem: environment %s is administratively disabled", shm_env); |
| exit (1); | |
| } | } |
| d_grp = getgrnam (d_groupname); | d_grp = getgrnam (d_groupname); |
| if (d_grp == NULL) { | if (d_grp == NULL) { |
| fprintf (stderr, "freem: invalid group '%s'\n", d_groupname); | logprintf (FM_LOG_FATAL, "freem: invalid group '%s'", d_groupname); |
| exit (1); | |
| } | } |
| d_gid = d_grp->gr_gid; | d_gid = d_grp->gr_gid; |
| d_user = getpwnam (d_username); | d_user = getpwnam (d_username); |
| if (d_user == NULL) { | if (d_user == NULL) { |
| fprintf (stderr, "freem: invalid user '%s'\n", d_username); | logprintf (FM_LOG_FATAL, "freem: invalid user '%s'", d_username); |
| exit (1); | |
| } | } |
| d_uid = d_user->pw_uid; | d_uid = d_user->pw_uid; |
| #if defined(__linux__) | #if defined(__linux__) |
| if (run_daemon == FALSE && group_member (d_gid) == 0) { | if (run_daemon == FALSE && group_member (d_gid) == 0) { |
| fprintf (stderr, "freem: you must be a member of the %s group to use environment %s\n", d_groupname, shm_env); | logprintf (FM_LOG_FATAL, "freem: you must be a member of the %s group to use environment %s", d_groupname, shm_env); |
| exit (1); | |
| } | } |
| #endif | #endif |
| if (run_daemon == TRUE) { | if (run_daemon == TRUE) { |
| if (geteuid () != 0 && nofork == FALSE) { | if (geteuid () != 0 && nofork == FALSE) { |
| fprintf (stderr, "freem: forking daemon must be run as root\n"); | logprintf (FM_LOG_FATAL, "freem: forking daemon must be run as root"); |
| exit (1); | |
| } | } |
| } | } |
| Line 529 int main (int argc, char **argv, char ** | Line 539 int main (int argc, char **argv, char ** |
| if ((run_daemon == TRUE) && (nofork == FALSE)) { | if ((run_daemon == TRUE) && (nofork == FALSE)) { |
| int fork_fd; | int fork_fd; |
| init_log (); | |
| /* daemonize */ | /* daemonize */ |
| fork_pid = fork (); | fork_pid = fork (); |
| if (fork_pid < 0) { | if (fork_pid < 0) { |
| fprintf (stderr, "freem: failure in fork()\r\n"); | logprintf (FM_LOG_FATAL, "environment error: failure in initial fork()"); |
| m_log (1, "failure in initial fork()\r\n"); | |
| exit (1); | |
| } | } |
| if (fork_pid > 0) { | if (fork_pid > 0) { |
| Line 545 int main (int argc, char **argv, char ** | Line 555 int main (int argc, char **argv, char ** |
| } | } |
| if (setsid () < 0) { | if (setsid () < 0) { |
| fprintf (stderr, "freem: failure in setsid()\r\n"); | logprintf (FM_LOG_FATAL, "environment error: failure in setsid()"); |
| m_log (1, "failure in setsid()\r\n"); | |
| exit (1); | |
| } | } |
| signal (SIGCHLD, SIG_IGN); | signal (SIGCHLD, SIG_IGN); |
| Line 555 int main (int argc, char **argv, char ** | Line 563 int main (int argc, char **argv, char ** |
| fork_pid = fork (); | fork_pid = fork (); |
| if (fork_pid < 0) { | if (fork_pid < 0) { |
| fprintf (stderr, "freem: failure in fork()\r\n"); | logprintf (FM_LOG_FATAL, "environment error: failure in second fork()"); |
| m_log (1, "failure in second fork()\r\n"); | |
| exit (1); | |
| } | } |
| if (fork_pid > 0) { | if (fork_pid > 0) { |
| logprintf (FM_LOG_DEBUG, "environment: exiting from second fork()"); | |
| exit (0); | exit (0); |
| m_log (1, "exiting from second fork"); | |
| } | } |
| umask (0); | umask (0); |
| Line 574 int main (int argc, char **argv, char ** | Line 580 int main (int argc, char **argv, char ** |
| } | } |
| if (geteuid () == 0) { | if (geteuid () == 0) { |
| /* shed privileges */ | |
| fprintf (stderr, "freem: switching to group %s\n", d_groupname); | /* shed privileges */ |
| m_log (1, "switching groups"); | logprintf (FM_LOG_INFO, "environment: switching to group %s", d_groupname); |
| if (setgid (d_gid) == -1) { | if (setgid (d_gid) == -1) { |
| fprintf (stderr, "freem: failure switching GID\n"); | logprintf (FM_LOG_FATAL, "environment error: failure switching GID"); |
| m_log (1, "failure switching GIDs"); | |
| exit (1); | |
| } | } |
| if (d_uid != geteuid ()) { | if (d_uid != geteuid ()) { |
| fprintf (stderr, "freem: switching to username %s\n", d_username); | |
| m_log (1, "switching users"); | logprintf (FM_LOG_INFO, "environment: switching to username %s", d_username); |
| if (setuid (d_uid) == -1) { | if (setuid (d_uid) == -1) { |
| fprintf (stderr, "freem: failure switching UID\n"); | logprintf (FM_LOG_FATAL, "environment error: failure switching UID"); |
| m_log (1, "failure switching UIDs"); | |
| exit (1); | |
| } | } |
| } | } |
| } | } |
| else { | else { |
| fprintf (stderr, "not euid 0"); | logprintf (FM_LOG_INFO, "environment: not running as superuser; not shedding privileges"); |
| } | } |
| freopen ("/dev/null", "r", stdin); | freopen ("/dev/null", "r", stdin); |
| Line 624 int main (int argc, char **argv, char ** | Line 624 int main (int argc, char **argv, char ** |
| errsav = errno; | errsav = errno; |
| if (pid_fd < 0) { | if (pid_fd < 0) { |
| fprintf (stderr, "freem: could not open PID file %s [%s]\n", pid_file_path, strerror (errsav)); | logprintf (FM_LOG_FATAL, "environment error: could not open PID file %s [%s]", pid_file_path, strerror (errsav)); |
| m_log (1, "freem: could not open PID file"); | |
| m_log (1, strerror (errsav)); | |
| exit (1); | |
| } | } |
| if (lockf (pid_fd, F_TLOCK, 0) < 0) { | if (lockf (pid_fd, F_TLOCK, 0) < 0) { |
| errsav = errno; | errsav = errno; |
| fprintf (stderr, "freem: could not lock PID file [%s]\n", strerror (errsav)); | logprintf (FM_LOG_FATAL, "environment error: could not lock PID file [%s]", strerror (errsav)); |
| m_log (1, "freem: could not lock PID file - perhaps already running?"); | |
| m_log (1, strerror (errsav)); | |
| exit (1); | |
| } | } |
| sprintf (pidfile_buf, "%ld\n", (long) getpid ()); | sprintf (pidfile_buf, "%ld\n", (long) getpid ()); |
| Line 725 int main (int argc, char **argv, char ** | Line 719 int main (int argc, char **argv, char ** |
| } | } |
| /* make this the startup routine */ | /* make this the startup routine */ |
| snprintf (startuprou, 256, "^%s\201", cli_rtn_name); | snprintf (startuprou, sizeof (startuprou) - 1, "^%s\201", cli_rtn_name); |
| /* re-work the namespace config to search for the | /* re-work the namespace config to search for the |
| routine in the discovered path */ | routine in the discovered path */ |
| if (cli_rtn_name[0] == '%') { | if (cli_rtn_name[0] == '%') { |
| snprintf (rou0plib, 256, "%s\201", cli_rtn_path); | snprintf (rou0plib, sizeof (rou0plib) - 1, "%s\201", cli_rtn_path); |
| snprintf (rou1plib, 256, "%s\201", cli_rtn_path); | snprintf (rou1plib, sizeof (rou1plib) - 1, "%s\201", cli_rtn_path); |
| } | } |
| else { | else { |
| snprintf (rou0path, 256, "%s\201", cli_rtn_path); | snprintf (rou0path, sizeof (rou0path) - 1, "%s\201", cli_rtn_path); |
| snprintf (rou1path, 256, "%s\201", cli_rtn_path); | snprintf (rou1path, sizeof (rou1path) - 1, "%s\201", cli_rtn_path); |
| } | } |
| Line 775 int main (int argc, char **argv, char ** | Line 769 int main (int argc, char **argv, char ** |
| pid_t stop_requester; | pid_t stop_requester; |
| if (run_daemon == FALSE) { | if (run_daemon == FALSE) { |
| fprintf (stderr, "freem: re-run with --daemon or -d command-line flags\r\n"); | logprintf (FM_LOG_FATAL, "freem: re-run with --daemon or -d command-line flags"); |
| cleanup (); | |
| exit (1); | |
| } | } |
| stcpy (verstr, FREEM_VERSION_STR); | stcpy (verstr, FREEM_VERSION_STR); |
| stcnv_m2c (verstr); | stcnv_m2c (verstr); |
| fprintf (stderr, "Coherent Logic Development FreeM version %s\r\n", verstr); | fprintf (stderr, "Coherent Logic Development FreeM version %s\r\n", verstr); |
| fprintf (stderr, "freem: shared memory for environment %s initialized (%ld bytes of shared memory @ '%p')\r\nfreem: system ready\r\n", shm_env, (long) shm_init_size, shm_config->dta); | logprintf (FM_LOG_INFO, "freem: shared memory for environment %s initialized (%ld bytes of shared memory @ '%p')", shm_env, (long) shm_init_size, shm_config->dta); |
| for (;;) { | for (;;) { |
| Line 795 int main (int argc, char **argv, char ** | Line 787 int main (int argc, char **argv, char ** |
| job_slot_t *slot; | job_slot_t *slot; |
| fprintf (stderr, "freem: entering maintenance mode\r\n"); | logprintf (FM_LOG_WARNING, "environment: entering maintenance mode"); |
| m_log (1, "freem: entering maintenance mode"); | |
| for (slot = shm_config->hdr->jobtab_head; slot != NULL; slot = slot->next) { | for (slot = shm_config->hdr->jobtab_head; slot != NULL; slot = slot->next) { |
| Line 815 int main (int argc, char **argv, char ** | Line 806 int main (int argc, char **argv, char ** |
| connected_jobs = job_count (); | connected_jobs = job_count (); |
| fprintf (stderr, "freem: STOP requested by pid %d\r\n", stop_requester); | logprintf (FM_LOG_INFO, "environment: STOP requested by pid %ld", stop_requester); |
| fprintf (stderr, "freem: there are %d job(s) connected to this environment\r\n", connected_jobs); | logprintf (FM_LOG_INFO, "environment: there are %d job(s) connected to this environment", connected_jobs); |
| if (connected_jobs > 1) { | if (connected_jobs > 1) { |
| fprintf (stderr, "freem: asking non-daemon job(s) to disconnect and halt...\r\n"); | logprintf (FM_LOG_INFO, "environment: asking non-daemon job(s) to disconnect and halt..."); |
| job_request_all_stop (); | job_request_all_stop (); |
| fprintf (stderr, "freem: waiting 5 seconds for job(s) to disconnect...\r\n"); | logprintf (FM_LOG_INFO, "environment: waiting 5 seconds for job(s) to disconnect..."); |
| sleep (5); | sleep (5); |
| connected_jobs = job_count (); | connected_jobs = job_count (); |
| if (connected_jobs > 1) { | if (connected_jobs > 1) { |
| fprintf (stderr, "freem: sending SIGTERM to %d job(s)...\r\n", connected_jobs); | logprintf (FM_LOG_INFO, "environment: sending SIGTERM to %d job(s)...", connected_jobs); |
| job_signal_all (SIGTERM); | job_signal_all (SIGTERM); |
| fprintf (stderr, "freem: waiting 5 seconds for job(s) to disconnect...\r\n"); | logprintf (FM_LOG_INFO, "environment: waiting 5 seconds for job(s) to disconnect..."); |
| sleep (5); | sleep (5); |
| } | } |
| connected_jobs = job_count (); | connected_jobs = job_count (); |
| if (connected_jobs > 1) { | if (connected_jobs > 1) { |
| fprintf (stderr, "freem: sending SIGKILL to %d job(s)...\r\n", connected_jobs); | logprintf (FM_LOG_INFO, "environment: sending SIGKILL to %d job(s)...", connected_jobs); |
| job_signal_all (SIGKILL); | job_signal_all (SIGKILL); |
| } | } |
| Line 846 int main (int argc, char **argv, char ** | Line 837 int main (int argc, char **argv, char ** |
| } | } |
| fprintf (stderr, "freem: terminating\r\n"); | logprintf (FM_LOG_INFO, "freem: terminating"); |
| cleanup (); | cleanup (); |
| exit (0); | exit (0); |
| Line 894 int main (int argc, char **argv, char ** | Line 885 int main (int argc, char **argv, char ** |
| stcpy (verstr, FREEM_VERSION_STR); | stcpy (verstr, FREEM_VERSION_STR); |
| stcnv_m2c (verstr); | stcnv_m2c (verstr); |
| snprintf (version, 255, "\r\nCoherent Logic Development FreeM version %s [DIALECT: %s%s]\r\n\201", verstr, m_dialect, (restricted_mode == TRUE ? "/RESTRICTED" : "")); | snprintf (version, sizeof (version) - 1, "\r\nCoherent Logic Development FreeM version %s [DIALECT: %s%s]\r\n\201", verstr, m_dialect, (restricted_mode == TRUE ? "/RESTRICTED" : "")); |
| write_m (version); | write_m (version); |
| snprintf (version, 255, "Copyright (C) 2014, 2020, 2021, 2023, 2025 Coherent Logic Development LLC\r\n\r\n\201"); | snprintf (version, sizeof (version) - 1, "Copyright (C) 2014, 2020, 2021, 2023, 2025 Coherent Logic Development LLC\r\n\r\n\201"); |
| write_m (version); | write_m (version); |
| /* | /* |
| Line 914 int main (int argc, char **argv, char ** | Line 905 int main (int argc, char **argv, char ** |
| if (dx_mode) { | if (dx_mode) { |
| char k_buf[512]; | char k_buf[512]; |
| snprintf (k_buf, 512 - 1, "%%TMPINITMCODE\201\201"); | snprintf (k_buf, sizeof (k_buf) - 1, "%%TMPINITMCODE\201\201"); |
| symtab (set_sym, k_buf, dx_mcode); | symtab (set_sym, k_buf, dx_mcode); |
| const_define (k_buf, dx_mcode); | const_define (k_buf, dx_mcode); |
| } | } |
| Line 922 int main (int argc, char **argv, char ** | Line 913 int main (int argc, char **argv, char ** |
| if (routine_mode) { | if (routine_mode) { |
| char k_buf[512]; | char k_buf[512]; |
| snprintf (k_buf, 512 - 1, "%%TMPINITROUTINE\201\201"); | snprintf (k_buf, sizeof (k_buf) - 1, "%%TMPINITROUTINE\201\201"); |
| symtab (set_sym, k_buf, startup_routine); | symtab (set_sym, k_buf, startup_routine); |
| const_define (k_buf, startup_routine); | const_define (k_buf, startup_routine); |
| } | } |