
I’m not 100% sure if we consider this relevant - also the title auto fetch didn’t work and I didn’t know whether I should include the full title or the first part of the sentence?
score 1 · canonical

I’m not 100% sure if we consider this relevant - also the title auto fetch didn’t work and I didn’t know whether I should include the full title or the first part of the sentence?
score 1 · canonical

I’m not sure that’s correct? There’s a significant difference between announcing a new product, and describing how that product is likely ineffective
score 1 · canonical

This is incomplete as it fails to discuss the suffering involved in this kind of work :D
score 1 · canonical

I just tried to post this :D
Sky even behaved reasonably: they said that this is their IP, but because they recognized it was historically significant allowed him to publish the images as long as he had red acted any personal info or potentially unrelated IP.
score 1 · canonical

I think I misread what they were saying (or they phrased it poorly). They presumably mean arbitrary code execution: e.g the hacker has overwritten a function pointer and taken over the control flow rather than “the server has provided the executable code”.
I feel the phrasing at least is weird, but if we assume the above then it’s just a standard UaF->code pointer corruption. Handling ASLR, varying code layout, etc is a fairly well understood problem space - assuming the right info leaks exist those mitigations can be fairly easily resolved, the mitigations are insufficient on their own, they just increase the number of concurrent bugs needed (but for experienced attackers they’re still just a minor step).
score 1 · canonical

This does not explain how a UaF results in server provided code becoming executable. My only explanation would be if curl handles PAC files and uses a JS engine with a JIT or similar that maps a page as executable.
score 1 · canonical

Everyone complained when apple said web apps were the way to make apps for the iPhone, and now we have the App Store.
score 1 · canonical

I don’t really understand the problem here because fairscan is under GPL and all Ente code appears to be AGPL, which is allowed. Ente also did this quite openly (the blog post says that they even contacted the author).
Opensource is not public domain. It frustrates me how often people act like it is.
The entire point of all of the open source licenses is that they are protected by copyright. Anyone can distribute a derivative work, but they can’t remove the original copyright owner, nor claim to be the copyright owner. Similarly they can’t relicense beyond what the original license permits, and even if they do, they still cannot remove the copyright information because the original author[s] have not rescinded their ownership of the code.
But, yeah, Ente could be a bit more thankful and handling this more elegantly.
What Ente did was steal open source code and claim ownership of code that was not theirs to own. They cannot claim ownership of derived code.
score 1 · canonical

Nice to see someone immediately addressing symmetric cryptography being functionally unimpacted by quantum computing
score 1 · canonical

honestly at this point I have no idea sorry - I basically live in the land of arm where there’s no ordering :D
score 1 · canonical

I thought some of UB was to deal with different CPU behavior.
That’s what implementation defined behavior means.
Let’s say you’re on a machine where integer overflow is defined as trapping. Because it is UB, the fact that it has defined behavior is irrelevant, their are no constraints on the compiler. For example, say you have code that does this:
int foo(int a, int b) {
return a + b;
}
...
int x = INT_MAX;
int y = cond ? 0 : 1;
foo(x, y);
If cond is true, then a + b is INT_MAX + 1 which is UB, so cond must always be false.
It’s really important to understand that the compiler is not detecting this directly, a lot of optimizations are constraint based, and the result of applying those constraints is that UB paths get dropped.
I hate that compilers assume that. I know that programmers don’t intentionally want to invoke UB in C, but there are so damn many footguns in C that I seriously doubt any non-trivial C program is completely UB free.
Yes, but for the majority of cases where this happens, the problem is not that the compiler is assuming UB operations can’t happen. The problem is that operations with well defined behavior are being labeled as UB. Most of the foot guns around “the compiler removed this code” boil down to “the developer wrote code around well defined behavior on the platform, but the spec says it is undefined”. The moment that implementation defined behavior stops being labeled as UB, many of those foot guns go away.
score 1 · canonical

Classifying a call to realloc with a size of 0 as undefined behavior would allow POSIX to define the otherwise undefined behavior however they please.
What posix says is irrelevant though. realloc is specified as part of the language, compilers are aware of the semantics, and the platform providing defined behavior is irrelevant. If the intent is to permit a platform to specified the contract for realloc, the solution is implementation defined or unspecified behavior, not to label it UB.
Labeling it UB means that
void *foo(void* ptr, int newsize) {
if (!newsize) report("zero sized realloc")
return realloc(ptr, newsize);
}
can be optimized to
void *foo(void* ptr, int newsize) {
return realloc(ptr, newsize);
}
If the compiler discovers that newsize is zero, this can be compiled to
_foo:
_some_other_function:
...
That’s literally the definition of what UB allows. The underlying implementation is completely irrelevant, by saying realloc(ptr, 0) is UB they are not saying “the implementation can change the contract for a zero sized realloc”, they are saying that the behavior of an implementation in response to a zero sized realloc is irrelevant.
More realistically a compiler might choose to lower realloc(.., 0) or equivalently malloc(0) to a trap: it’s UB, so it is permitted to do so, and malloc(0) and realloc(…, 0) are generally considered bad things to do for a variety of reasons. So trapping when that happens means that the mistake is identified early (it is definitionally incorrect code), helping the developer fix it, and it helps the implementation by removing the need to support it. This applies even if the implementation intentionally supports it.
You cannot have a definition of UB in which there are no constraints on how a compiler treats signed integer overflow, while also saying that their are constraints on how realloc(ptr, 0) is interpreted. If a standard wants to say “the implementation can define the behavior in this case”, the solution is to say it is implementation defined.
score 1 · canonical

So we agree that UB has nothing to do with cross platform compatibility.
But your justification for the use of UB in cases like this is an argument against any implementation defined behavior, and it brings an immediate rebuttal
Any conforming and correct C program that avoids implementation defined behavior will behave identically across all platforms.
There is absolutely no difference in the degree of difficulty in avoiding all UB and avoiding all IDB: the logic required to avoid invoking UB for any given operation is that same logic required to avoid IDB. The result of making an error is the same in the overwhelming majority of cases, except by labeling something UB the compiler can disregard the behavior that it applies in other places.
There is not difference in cross platform compatibility: the same incompatible code exists in both cases, the only difference is that by claiming something to be UB, code that is correct with respect to the target will behave in accordance with that hardware, except for unpredictable occasions where it will not, and it is not possible for a developer to ever reason about whether or not that happens, because UB is a global, not local, property of the program.
So I have some questions, and I’m curious about what you feel that answers are - obviously you’re under no obligation to respond, but I am curious. I’m just saying IDB here, but IDB and unspecified are in the same general bucket for the purpose of this thread.
score 1 · canonical

Undefined behavior exists for a number of reasons. It allows implementations to support extensions, manage interactions with hardware-based safety mechanisms
No.
No. No. No.
UB has nothing to do with supporting different hardware behaviour. At all.
Let’s take signed integer overflow. That is UB. This does not mean that you can write a + b < a as an overflow check if that’s the behaviour on your hardware. Being UB means that if you code does this, you code is wrong. It does not check for overflow, it either:
This is ostensibly useful for vectorizing loop induction variables, but I’m not super convinced.
There are
(1) is obvious. (2) and (3) are what support different implementations and hardware, etc. The behavior is still defined, the code that triggers them is correct (per the AM, you’re still free to have logic bugs), the compiler is constrained, it cannot assume it doesn’t exist.
And UB is behavior that is invalid on the AM, and anything invalid on the AM can be assumed to not happen.
(C++ also has Erroneous behavior, but that basically just exists because the standard wants to be able to say a common error is an error, but recognize the failure mode is so catastrophic that it requires the compiler to have safe-ish behavior)
Another misconception is that the compiler is detecting and optimizing UB it finds. What actually happens is the compiler encounters some code, and assumes that UB does not happen. e.g lets look a different case of ub: null dereferences.
void do_thing(int a) {
precondition(a > 0);
userid = a;
}
Can a call to this function set userid to 0? let’s look at that precondition call. It turns out to be a macro:
#define precondition(x) if (!(x)) *(char*)0=0;
From the compiler’s point of view, that macro means that if a < 0 a null dereference occurs. That is UB, so it can’t happen, and the branch disappears, and the precondition does nothing. This is not hypothetical: there was a period where dereferencing a nullptr was considered a valid way to force a trap. Then one day gcc started optimizing on the basis of it being UB, and a whole bunch of security bugs went from theoretical to real.
And to be even more explicit about what UB permits:
void do_thing(int a) {
a = -1;
precondition(a > 0);
userid = a;
}
can call an arbitrary function.
score 1 · canonical

memset_s: more or less yes, that is the core of what this article is talking about.
It sounds like memset_explicit might be the “solution”. This requires the backend be aware of these semantics, and while I don’t know about GCC, llvm’s register allocation does not carry such info and I’ve generally encountered push back against adding the data required to track such semantics (though in my case in the context of pointer authentication). IMO it would be a general win for a lot of security related purposes.
score 1 · canonical

The compiler knows the semantics of memset, specifically that it can be treated as a dead store. memset_s (and the other _s functions) have defined semantics of guaranteeing a write, even if it’s dead - a compiler that tried lowering them such that they did not zero the memory would be nonconforming. As a result they essentially just don’t special case them at all.
score 1 · canonical

Yeah, the ideal fix would be some kind of “scrub this value” qualifier/attribute that gets passed to the backend
score 1 · canonical

memset_s serves that purpose, but this is the specific problem being discussed in the article: if the value is not in memory you don’t need to zero the memory, but by calling memset[_s] you force the compiler to spill the value onto the stack for the express purpose of zeroing it.
score 1 · canonical

Ugh, getting back to properly distributed random from the FP representation is almost as annoying as generating them properly in the first place. I have a recollection that most approaches now only give you 27/53 bits of entropy due to the misery of dealing with over representation of more heavily fractional values. Essentially generate a random value between 1 and 2 (which is easy in a bitwise manner) and then subtract 1.
score 1 · canonical
Steam’s linux gaming support is built on wine, so assuming a complete port of wine you’d get all of that
score 1 · canonical