On 6/17/20 3:11 PM, Richard Biener wrote: > On Wed, 17 Jun 2020, H.J. Lu wrote: > >> On Wed, Jun 17, 2020 at 5:33 AM Richard Biener <rguent...@suse.de> wrote: >>> >>> On Wed, 17 Jun 2020, H.J. Lu wrote: >>> >>>> On Wed, Jun 17, 2020 at 5:00 AM Richard Biener <rguent...@suse.de> wrote: >>>>> >>>>> On Wed, 17 Jun 2020, H.J. Lu wrote: >>>>> >>>>>> On Wed, Jun 17, 2020 at 1:59 AM Richard Biener >>>>>> <richard.guent...@gmail.com> wrote: >>>>>>> >>>>>>> On Mon, Jun 15, 2020 at 5:30 PM Matthias Klose <d...@ubuntu.com> wrote: >>>>>>>> >>>>>>>> PR lto/95604 was seen when checking for binaries without having CET >>>>>>>> support in a >>>>>>>> distro archive, for binaries built with LTO optimization. The >>>>>>>> hardening flag >>>>>>>> -fcf-protection=full is passed in CFLAGS, and maybe should be passed >>>>>>>> in LDFLAGS >>>>>>>> as well. However to make it work when not passed to the link step, it >>>>>>>> should be >>>>>>>> extracted from the options found in the lto opts section. >>>>>>>> >>>>>>>> Richard suggested two solutions offline. I checked that both fix the >>>>>>>> test case. >>>>>>>> Which one to install? Also ok for the 9 and 10 branches? >>>>>>> >>>>>>> I guess even though variant two is simpler it doesn't make much sense to >>>>>>> have differing settings of -fcf-protection between different functions? >>>>>>> HJ? >>>>>> >>>>>> -fcf-protection is applied to a file, not a function since CET marker >>>>>> is per file. >>>>>> >>>>>>> So looking at variant one, >>>>>>> >>>>>>> @@ -287,6 +287,18 @@ >>>>>>> foption->orig_option_with_args_text); >>>>>>> break; >>>>>>> >>>>>>> + case OPT_fcf_protection_: >>>>>>> + /* Append or check identical. */ >>>>>>> + for (j = 0; j < *decoded_options_count; ++j) >>>>>>> + if ((*decoded_options)[j].opt_index == foption->opt_index) >>>>>>> + break; >>>>>>> + if (j == *decoded_options_count) >>>>>>> + append_option (decoded_options, decoded_options_count, >>>>>>> foption); >>>>>>> + else if (strcmp ((*decoded_options)[j].arg, foption->arg)) >>>>>>> + warning (input_location, "option %s with different values", >>>>>>> + foption->orig_option_with_args_text); >>>>>>> + break; >>>>>>> >>>>>>> you are always streaming a -fcf-protection option so the if (j == >>>>>>> *decoded_options_count) >>>>>>> case shouldn't ever happen but I guess it's safe to leave the code >>>>>>> as-is. Can you >>>>>>> amend the warning with the option that prevails? Maybe >>>>>>> >>>>>>> + else if (strcmp ((*decoded_options)[j].arg, foption->arg)) >>>>>>> { >>>>>>> static bool noted; >>>>>>> + warning (input_location, "option %s with different values", >>>>>>> + foption->orig_option_with_args_text); >>>>>>> if (!noted) >>>>>>> { >>>>>>> inform ("%s will be used instead", >>>>>>> (*decoded_options)[j].orig_option_with_args_text); >>>>>>> noted = true; >>>>>>> } >>>>>>> >>>>>>> I guess input_location is simply zero so the diagnostic doesn't >>>>>>> contain the actual file we're >>>>>>> looking at. Something to improve I guess (also applyign to other >>>>>>> diagnostics we emit). >>>>>>> >>>>>>> Otherwise looks OK. >>>>>>> >>>>>>> Please wait for HJ in case he'd like to go with option two. >>>>>>> >>>>>> >>>>>> I prefer option one. But what happens if input files are compiled >>>>>> with different -fcf-protection settings? >>>>> >>>>> You get a warning and the first option setting wins (and I requested >>>>> to inform the user which that is). >>>>> >>>> >>>> I think it should be an error and the user should explicitly specify the >>>> option with -lfto in the final link command. >>> >>> But AFAIK ld will not reject linking objects with mismatched settings? >> >> Linker will silently change CET run-time behavior. >> >>> Does -fcf-protection have effects "early" (up to IPA)? That is, is it >>> safe to turn it on only post-IPA? >> >> I think so. We don't do anything with SHSTK. For IBT, we just insert an >> ENDBR when we output the indirect branch target. >> >>> So yeah, if the user provided an explicit -fcf-protection option at link >>> we honor that (but with the current patch we'd still warn about conflicts >> >> I don't think we should warn about the explicit -fcf-protection option at >> link >> time. >> >>> between the original TU setting - but not conflicts with the setting >>> at link time). If we want to error on mismatches but allow if at link >>> time a setting is specified that needs extra code (it would be the >>> first time we have this behavior). >>> >> >> I think we should give an error if there are any mismatches in >> inputs and let the explicit -fcf-protection option at link time override >> -fcf-protection options in inputs . > > Note the linker will then still silently change CET run-time behavior > when there's a non-LTO object involved in the link that has > mismatched settings. > > Matthias - currently find_and_merge_options does not have access > to the link-time options, you'd need to pass them down (they are > in 'decoded_options', gathered via get_options_from_collect_gcc_options). > Note the option overriding simply happens because we append the link-time > options to any options coming from the IL file so the only thing you > need to do is turn the warning back to an error but guard that with > the presence of the option in the link-time options. > > Richard.
here's an updated patch. checked that it errors out with .o files compiled with different -fcf-protection values, and checked that overriding the -fcf-protection value at link time works. Matthias
# DP: Fix PR lto/95604, proposed patch PR lto/95604 * lto-wrapper.c (merge_and_complain): Add decoded options as parameter, error on different values for -fcf-protection. (append_compiler_options): Pass -fcf-protection option. (find_and_merge_options): Add decoded options as parameter, pass decoded_options to merge_and_complain. (run_gcc): Pass decoded options to find_and_merge_options. * lto-opts.c (lto_write_options): Pass -fcf-protection option. --- a/src/gcc/lto-opts.c +++ b/src/gcc/lto-opts.c @@ -94,6 +94,21 @@ lto_write_options (void) : "-fno-pie"); } + if (!global_options_set.x_flag_cf_protection) + { + append_to_collect_gcc_options ( + &temporary_obstack, &first_p, + global_options.x_flag_cf_protection == CF_NONE + ? "-fcf-protection=none" + : global_options.x_flag_cf_protection == CF_FULL + ? "-fcf-protection=full" + : global_options.x_flag_cf_protection == CF_BRANCH + ? "-fcf-protection=branch" + : global_options.x_flag_cf_protection == CF_RETURN + ? "-fcf-protection=RETURN" + : ""); + } + /* If debug info is enabled append -g. */ if (debug_info_level > DINFO_LEVEL_NONE) append_to_collect_gcc_options (&temporary_obstack, &first_p, "-g"); --- a/src/gcc/lto-wrapper.c +++ b/src/gcc/lto-wrapper.c @@ -192,11 +192,14 @@ static void merge_and_complain (struct cl_decoded_option **decoded_options, unsigned int *decoded_options_count, struct cl_decoded_option *fdecoded_options, - unsigned int fdecoded_options_count) + unsigned int fdecoded_options_count, + struct cl_decoded_option *decoded_cl_options, + unsigned int decoded_cl_options_count) { unsigned int i, j; struct cl_decoded_option *pic_option = NULL; struct cl_decoded_option *pie_option = NULL; + struct cl_decoded_option *cf_protection_option = NULL; /* ??? Merge options from files. Most cases can be handled by either unioning or intersecting @@ -211,6 +214,17 @@ merge_and_complain (struct cl_decoded_op In absence of that it's unclear what a good default is. It's also difficult to get positional handling correct. */ + /* Look for a -fcf-protection option in the link-time options + which overrides any -fcf-protection from the lto sections. */ + for (i = 0; i < decoded_cl_options_count; ++i) + { + struct cl_decoded_option *foption = &decoded_cl_options[i]; + if (foption->opt_index == OPT_fcf_protection_) + { + cf_protection_option = foption; + } + } + /* The following does what the old LTO option code did, union all target and a selected set of common options. */ for (i = 0; i < fdecoded_options_count; ++i) @@ -287,6 +301,23 @@ merge_and_complain (struct cl_decoded_op foption->orig_option_with_args_text); break; + case OPT_fcf_protection_: + /* Default to link-time option, else append or check identical. */ + if (!cf_protection_option) + { + for (j = 0; j < *decoded_options_count; ++j) + if ((*decoded_options)[j].opt_index == foption->opt_index) + break; + if (j == *decoded_options_count) + append_option (decoded_options, decoded_options_count, foption); + else if (strcmp ((*decoded_options)[j].arg, foption->arg)) + fatal_error (input_location, + "option -fcf-protection with mismatching values" + " (%s, %s)", + (*decoded_options)[j].arg, foption->arg); + } + break; + case OPT_O: case OPT_Ofast: case OPT_Og: @@ -631,6 +662,7 @@ append_compiler_options (obstack *argv_o case OPT_fopenacc: case OPT_fopenacc_dim_: case OPT_foffload_abi_: + case OPT_fcf_protection_: case OPT_g: case OPT_O: case OPT_Ofast: @@ -988,12 +1020,14 @@ find_crtoffloadtable (void) /* A subroutine of run_gcc. Examine the open file FD for lto sections with name prefix PREFIX, at FILE_OFFSET, and store any options we find in OPTS - and OPT_COUNT. Return true if we found a matchingn section, false + and OPT_COUNT. Return true if we found a matching section, false otherwise. COLLECT_GCC holds the value of the environment variable with the same name. */ static bool find_and_merge_options (int fd, off_t file_offset, const char *prefix, + struct cl_decoded_option *decoded_cl_options, + unsigned int decoded_cl_options_count, struct cl_decoded_option **opts, unsigned int *opt_count, const char *collect_gcc) { @@ -1040,7 +1074,9 @@ find_and_merge_options (int fd, off_t fi else merge_and_complain (&fdecoded_options, &fdecoded_options_count, - f2decoded_options, f2decoded_options_count); + f2decoded_options, f2decoded_options_count, + decoded_cl_options, + decoded_cl_options_count); fopts += strlen (fopts) + 1; } @@ -1373,6 +1409,7 @@ run_gcc (unsigned argc, char *argv[]) } if (find_and_merge_options (fd, file_offset, LTO_SECTION_NAME_PREFIX, + decoded_options, decoded_options_count, &fdecoded_options, &fdecoded_options_count, collect_gcc)) { @@ -1576,6 +1613,7 @@ cont1: fatal_error (input_location, "cannot open %s: %m", filename); if (!find_and_merge_options (fd, file_offset, OFFLOAD_SECTION_NAME_PREFIX, + decoded_options, decoded_options_count, &offload_fdecoded_options, &offload_fdecoded_options_count, collect_gcc))