This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [RFC 6/6] Cache a copy of the user's shell on macOS


On 2018-09-26 7:11 a.m., Tom Tromey wrote:
> +/* If $SHELL is restricted, try to cache a copy.  Starting with El
> +   Capitan, macOS introduced System Integrity Protection.  Among other
> +   things, this prevents certain executables from being ptrace'd.  In
> +   particular, executables in /bin, like most shells, are affected.
> +   To work around this, while preserving command-line glob expansion
> +   and redirections, gdb will cache a copy of the shell.  Return true
> +   if all is well -- either the shell is not subject to SIP or it has
> +   been successfully cached.  Returns false if something failed.  */
> +
> +static bool
> +maybe_cache_shell ()
> +{
> +  /* SF_RESTRICTED is defined in sys/stat.h and lets us determine if a
> +     given file is subject to SIP.  */
> +#ifdef SF_RESTRICTED
> +
> +  /* If a check fails we want to revert -- maybe the user deleted the
> +     cache while gdb was running, or something like that.  */
> +  copied_shell = nullptr;
> +
> +  const char *shell = get_shell ();
> +  if (!IS_ABSOLUTE_PATH (shell))
> +    {
> +      warning (_("This version of macOS has System Integrity Protection.\n\
> +Normally gdb would try to work around this by caching a copy of your shell,\n\
> +but because your shell (%s) is not an absolute path, this is being skipped."),
> +	       shell);
> +      return false;
> +    }
> +
> +  struct stat sb;
> +  if (stat (shell, &sb) < 0)
> +    {
> +      warning (_("This version of macOS has System Integrity Protection.\n\
> +Normally gdb would try to work around this by caching a copy of your shell,\n\
> +but because gdb could not stat your shell (%s), this is being skipped.\n\
> +The error was: %s"),
> +	       shell, safe_strerror (errno));
> +      return false;
> +    }
> +
> +  if ((sb.st_flags & SF_RESTRICTED) == 0)
> +    return true;
> +
> +  /* Put the copy somewhere like ~/Library/Caches/gdb/bin/sh.  */
> +  std::string new_name = get_standard_cache_dir ();
> +  if (!IS_DIR_SEPARATOR (new_name.back ()) && !IS_ABSOLUTE_PATH (shell))

I believe this !IS_ABSOLUTE_PATH check can never be true, since we would
have returned early if it was the case?  If so, this append is not needed

> +    new_name.push_back ('/');
> +  new_name.append (shell);
> +
> +  /* Maybe it was cached by some earlier gdb.  */
> +  if (stat (new_name.c_str (), &sb) != 0 || !S_ISREG (sb.st_mode))
> +    {
> +      TRY
> +	{
> +	  copy_shell_to_cache (shell, new_name);
> +	}
> +      CATCH (ex, RETURN_MASK_ERROR)
> +	{
> +	  warning (_("This version of macOS has System Integrity Protection.\n\
> +Because `startup-with-shell' is enabled, gdb tried to work around SIP by\n\
> +caching a copy of your shell.  However, this failed:\n\
> +%s\n\
> +If you correct the problem, gdb will automatically try again the next time\n\
> +you \"run\".  To prevent these attempts, you can use:\n\
> +    set startup-with-shell off"),
> +		   ex.message);
> +	  return false;
> +	}
> +      END_CATCH
> +
> +      printf_filtered (_("Note: this version of macOS has System Integrity Protection.\n\
> +Because `startup-with-shell' is enabled, gdb has worked around this by\n\
> +caching a copy of your shell.  The shell used by \"run\" is now:\n\
> +    %s\n"),
> +		       new_name.c_str ());

I am not on Mac right now so I can't test, but I was wondering how
annoying it is to have this message every time you run and it succeeds.
I like that we explain what's happening when things go wrong, but is
it useful to explain it as well when everything works well?  Will the
user care?

Otherwise, this looks good to me, thanks!

Simon


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]