@@ -319,7 +319,39 @@ let run_external_command opts env command_tmpl =
319319 let cmd = render_command opts env command_tmpl in
320320 if opts.dry_run then Printf. printf " %s\n %!" cmd else
321321 let () = Logs. debug @@ fun m -> m " Command to be executed %s" cmd in
322- let res = Unix. system cmd in
322+ (* Get the user database entry to populate the basic environment from:
323+ we cannot trust an unprivileged user to supply $SHELL
324+ or allow them to impersonate someone else by setting custom $LOGNAME, etc.
325+ *)
326+ let user_pw_entry = Unix. getpwuid @@ Unix. getuid () in
327+ let make_var name value = Printf. sprintf " %s=%s" name value in
328+ let env = [|
329+ (* A knowingly safe executable lookup path.
330+ Since we do not use /usr/local, we do not need to include that.
331+ Executables in VyOS-specific directories are referred to by absolute paths
332+ in the operational command JSON cache,
333+ so we don't need to include those, either.
334+ *)
335+ make_var " PATH" " /usr/sbin:/usr/bin:/sbin:/bin" ;
336+ (* Standard UNIX variables *)
337+ make_var " HOME" user_pw_entry.pw_dir;
338+ make_var " USER" user_pw_entry.pw_name;
339+ make_var " LOGNAME" user_pw_entry.pw_name;
340+ make_var " SHELL" user_pw_entry.pw_shell;
341+ (* VyOS-specific variables *)
342+ make_var " vyos_data_dir" " /usr/share/vyos" ;
343+ make_var " vyos_validators_dir" " /usr/libexec/vyos/validators" ;
344+ make_var " vyos_completion_dir" " /usr/libexec/vyos/completion" ;
345+ make_var " vyos_libexec_dir" " /usr/libexec/vyos" ;
346+ make_var " vyos_op_scripts_dir" " /usr/libexec/vyos/op_mode" ;
347+ |]
348+ in
349+ let shell = " /bin/sh" in
350+ (* We use execve with an absolute path to Bourne shell rather than execvpe
351+ so that a user trying to do PATH=/bad/place vyos-op-run
352+ cannot achieve anything with that trick.
353+ *)
354+ let res = Unix. execve shell [|shell; " -c" ; cmd|] env in
323355 match res with
324356 | Unix. WEXITED 0 -> ()
325357 | _ ->
0 commit comments