Hardening xrdp with AppArmor

For some time now, I've been wanting to develop AppArmor profiles to confine xrdp and its components while running. Given that the xrdp process is open to the network, and xrdp-sesman runs as root, these are good candidates for security hardening.
Code changes
I found that some modifications to the code are necessary, however, to make this feasible. These changes are in my first commit, and they are relatively minor:

The function g_file_open() is used in numerous places to read things like configuration files. However, it is also used for writing files (e.g. PID files). The meat of the function, on the POSIX side, is as follows:
    rv =  open(file_name, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);

    if (rv == -1)
    {
        /* can't open read / write, try to open read only */
        rv =  open(file_name, O_RDONLY);
    }

This "try at first to open the file read/write" approach does not look good in a confinement framework. With AppArmor enabled, I see messages like this in the system log:
Mar 29 17:13:05 darkstar kernel: [  494.847515] audit: type=1400 audit(1648588385.232:73): apparmor="DENIED" operation="mknod" profile="/usr/sbin/xrdp" name="/etc/xrdp/xrdp_keyboard.ini" pid=1922 comm="xrdp" requested_mask="c" denied_mask="c" fsuid=123 ouid=123

At first, this left me scratching my head thinking, "Why is xrdp trying to write to the keyboard config file?" This didn't prevent xrdp from running correctly (as can happen with AppArmor if you're not careful), but security-minded admins would look askance at this.
There is a different call in the xrdp code that is used in a few places, that gives proper read-only access:
    fd = g_file_open_ex(file_name, 1, 0, 0, 0);

The parameters are four flags, requesting any combination of read access, write access, file creation, and file truncation. Most of the time, however, the above combination is used.
The first change I made was to turn all the g_file_open() calls that appear to need only read access, to use a proper read-only call. At first, I replaced them with calls like the above g_file_open_ex() example. But I realized that this function call is not very clear as to what it's doing unless you have the function signature in front of you, and it's used in exactly this form numerous times throughout the code. So I added a new function g_file_open_ro() that wraps this specific combination, and made my edits use that instead.
(Philosophically speaking, it would probably be better to have g_file_open() return a read-only descriptor, and add a new function like g_file_open_rw() or g_file_open_write() to return a writable one, so that the request for write access is explicit. But that's beyond the scope of this change.)

When the X server is executed, xrdp uses (when available) the Linux kernel's "no new privileges" feature to avoid potential fallout from invoking a setuid-root X server binary. This is a good thing to do, from a security perspective---but paradoxically, it gets in the way of further security hardening via AppArmor.
As it happens, the NoNewPrivs flag on a process prevents AppArmor from changing its confinement profile at all, even if the destination profile is more restrictive than the source one. What this means for xrdp is that the X server cannot be confined using a different, narrower profile than its parent (xrdp-sesman). If I attempt to do so, I get an error like this in the system log:
Apr  1 01:26:53 darkstar kernel: [ 4711.096244] audit: type=1400 audit(1648790813.552:691): apparmor="DENIED" operation="exec" info="no new privs" error=-1 profile="xrdp-sesman" name="/usr/lib/xorg/Xorg" pid=32353 comm="xrdp-sesman" requested_mask="x" denied_mask="x" fsuid=1000 ouid=0 target="xrdp-sesman//xorg"

This is not ideal, because the X server needs access to a lot fewer things than xrdp-sesman---and, in turn, the X server needs a few things that xrdp-sesman can do without. The two processes should not run with the same set of permissions.
I didn't want to get rid of the PR_SET_NO_NEW_PRIVS functionality, and I wanted to avoid adding a new configuration option, so what I did was add a check: If AppArmor is loaded, and the process is already confined in some way, then don't set NoNewPrivs. This is done by examining the content of /proc/self/attr/apparmor/current. The check is performed in a fail-safe way, so if anything goes wrong, the NoNewPrivs transition remains in effect.

Apparmor profiles
My second commit adds the new profiles. Some notes on these:

These profiles have been developed and tested on Ubuntu.

I tested only with Xorg and Xvnc (specifically Xtigervnc). I don't have the setup to test vnc-any or neutrinordp-any.

My changes are to the latest Git devel branch, but I tested by applying them to the Debian 0.9.19 package and compiling it on Ubuntu. (Ubuntu does not have 0.9.19 yet, as of this writing.)

I accommodated the FUSE stuff so that users can login/logout without issue, but I have no idea how to test that functionality.

The profile filenames follow the standard AppArmor convention of reflecting the absolute path of the installed binary. That said, the filenames are arbitrary, and are not parsed in any way.

The profiles themselves do contain absolute paths to various binaries, as AppArmor requires. These can be handled by parameterization (see e.g. @{Xorg} in the usr.sbin.xrdp-sesman profile), alternation (AppArmor supports {a,b,c} syntax in paths), and of course build-time substitutions<EMAIL_ADDRESS>

The profiles can be enabled by copying them into /etc/apparmor.d/, running /etc/init.d/apparmor force-reload (or rebooting), and restarting xrdp. Any prohibited actions will appear in the system log with apparmor="DENIED".

The profiles, as written, are in "enforce" mode. If you would like to experiment, you may want to enable them in "complain" mode. This will cause AppArmor to allow the application to do whatever it wants, but still log anything that it would have prohibited in "enforce" mode. All that is needed is to symlink the profiles into the /etc/apparmor.d/force-complain/ directory, and run /etc/init.d/apparmor force-reload (or reboot). Then, watch your system log for apparmor="ALLOWED" messages.
(Additionally, any deny AppArmor directives should be preceded with audit [if not already present] so that violations of same are logged. Normally, deny directives request "silent deny" behavior.)

Further work

Careful testing of the more advanced xrdp functionality will be needed, to ensure that the AppArmor profiles allow the necessary access. I've covered the basic use cases, but of course there are going to be more exotic setups that need to be supported.

Some adaptation to other Linux distributions will likely be needed. My experience is only with Debian/Ubuntu, however, so I'm not in a good position to address this.

There is one major hole in these AppArmor profiles, which will require additional work to address. It is this line in usr.sbin.xrdp-sesman:
  /etc/xrdp/startwm.sh Uxr,

This allows startwm.sh to be executed without confinement. The user session cannot run within the tightly-defined profile for xrdp-sesman; in fact, it probably can't run (or at least normally doesn't run) in any AppArmor profile at all. So this line allows that script an "escape hatch" out of the restrictions imposed on xrdp-sesman.
Because this is a shell script, however, there is a risk that could allow an attacker to take advantage of the "escape hatch." Rather than explain the issue here, I will link this excellent article that describes it in detail. (This is an old article, hence the Wayback link, but its analysis still reflects the situation today.)
The current versions of the startwm.sh script rely on xrdp-sesman setting up PATH and LANG variables (using pam_env) prior to its invocation. However, in an environment where this script represents a loosening of process confinement, at least PATH has to be treated as "tainted" data potentially originating from an attacker.
The simplest thing to do would be to put e.g. PATH=/bin:/usr/bin at the top of the script, and then set up PATH/LANG properly in shell space. A more complex solution would be to have a separate helper program for this: this helper would be executed unconfined, and then it does the pam_env stuff, reads DefaultWindowManager or whatever from sesman.ini, and finally exec()s the program. (Importantly, this helper cannot take arguments, as they may come from an attacker and AppArmor rules cannot match against those.)

I'll be happy to answer any questions, and revise these changes as needed.

@iskunk - first thing I should say is this is a great idea, and we should definitely get something in to support this.
My biggest concern is support.
For SELinux (which is only really used by Fedora/RHEL and derivatives), we ship xrdp as SELinux-ready, and leave it to the distribution to configure. There are two reasons for this:-

We're not in a position to dictate to the distros how they should use the product.
We're also not in a position to support the testing effort which would be required to support multiple distros using this. You quite rightly allude to testing above. We don't have any AppArmor experience on the team I'm aware of - I've been a RH admin in the past, so I'm fine with a subset of SELinux issues, but not all. So we're not really in a position to fully support this in the base product. That could lead to a worst-case where we ship this and then can't maintain it. No-one would be happy with that.

What I would be happy with is getting the product AppArmor ready so that either the distros can use it by adding profiles, or securlty-conscious users with the experience to admin this could easily get it configured. Shipping example profiles would be OK I think, provided they were basic.
Anyone else want to comment on this? I'd really like to find the most productive way forward on what could be a great feature.

PR update pushed. A few notes:

g_set_no_new_privs() could use some way of checking whether the process is running in a SELinux context (as NoNewPrivileges could interfere with that as well), but I don't know enough about that world to implement this correctly.

I did away with the #define PR_SET_NO_NEW_PRIVS 38 bit. I see that it dates from 2016, in the original commit that added the NoNewPrivileges call. I don't think it should be needed any more.

I moved the NoNewPrivileges transition up to the beginning of the X server child block. This is so that the AppArmor check inside g_set_no_new_privs() occurs before the env_set_user() call, so that the /proc file (which is owned by root) is opened by a process still running as root. This allows the addition of a same-user restriction to the AppArmor rule granting access to the /proc file.
This also has the side effect of running all the different types of X servers under NoNewPrivileges (when unconfined by AppArmor), not just Xorg. I tested that this isn't a problem for Xvnc, and I don't imagine it should be one for any of the others.

The commit that renames g_file_open() was produced mechanically, by running perl -pi -e 's/\bg_file_open\b/g_file_open_rw/g' on all source files and then reviewing manually, to avoid error.

It wasn't clear if you also wanted to rename g_file_open_ro() back to g_file_open(), making RO access implicit at the same time that RW access is explicit. If this is the case, then let me know, and I'll add another commit with that change.

Some comments re support:

Shipping AppArmor profiles would give distros a clear starting point for customization, and a clear owner/target for upstreaming their changes. I don't think it would amount to dictating usage, since there is a presumption that the project is willing to accommodate reasonable variations in how the product is deployed. (E.g. if a distro wants to put the binaries under /Programs/Xrdp/0.9.19/bin/ instead of /usr/{bin,sbin}/, then while /Programs/ would not fly in a PR, they might contribute some additional parameterization to facilitate it.)
Perhaps the situation is different with SELinux, due to the complexity of the rulesets?

Testing this is less a matter of AppArmor domain expertise, and more one of just being able to run xrdp through all the unusual and "creative" use cases that smaller groups of users rely on. It is not unlike the problem of code-coverage testing. Running through those odd use cases generates accesses that may not have been covered in the profile, possibly leading to breakage. Finding the precise modes of such breakage then allows the profile to be revised to allow those accesses.

This form of testing is not unique to AppArmor, of course---the same is needed when developing an SELinux ruleset, or seccomp filter, or possibly other forms of security confinement. If there is not already some way of running through the odd use cases automatically, in a way that can be packaged into a CI test, then I think there would be a lot to gain in developing one.

For what it's worth, AppArmor profiles are easier to grok than SELinux rulesets, due to being conceptually simpler (and less comprehensive). It's definitely not the same animal.

Fixed a thinko in sesman/session.c; should have used foo != 0 instead of !foo. This caused an error message to be logged on success.

Thanks @iskunk
I've enabled the CI on the above, part of which is a code formatting check to see if the code more-of-less complies with the coding standard on the wiki. As a hint you can run the scripts/run_astyle.sh script before pushing.
You raise an interesting point regarding SELinux which AFAIK doesn't need to disable NNP. It's been a while since I've looked at this though, and I'm not sure I can trust my memory. I'll go away and do a bit of research and get back to you.

The NNP disable test isn't needed for SELinux - the SELinux policy included with Fedora allows a process with NNP set to pivot to the SELinux unconfined_t process type which is all that is needed.
While it would be great to have scenario-based testing for releases, we don't have any at the moment - just unit testing for new features. So given we can't regression-test these profiles easily, I don't think we can enable them as part of the base product. I'd b happy to ship examples which the destros could use as a basis - I think the upstreaming point you make is a good one.

Updated the code formatting, used != 0 on the g_strcmp() call for clarity, and rebased.
As I understand it, NNP generally prohibits security transitions on a process because there is no easy way to verify that the process permissions afterward are a subset of those before. However, there is an exception to this when transitioning from the unconfined state, because security restrictions are never going to increase the permissions of an unconfined process.
I think that's probably what's going on with the Fedora SELinux config. I suspect that if they were to take an approach similar to the one here (confine both xrdp-sesman and Xorg, but with different rulesets, thereby requiring a transition when exec'ing Xorg), then skipping NNP would likewise become necessary.
Please let me know if there's anything else you'd like to see polished further.

The default Fedora SELinux policy is as basic as you can imagine. Essentially the daemons run as process type unconfined_service_t, where they have a few restrictions on what they can do, and the session and the X server run as unconfined_t (even fewer restrictions) which is intended for interactive user sessions only.
Regarding your comment on startwm.sh, on Fedora this runs as unconfined_t as a standard user, which is in-line with how interactive sessions are treated by default.
If particular shops want to introduce a more restrictive policy, by running xrdp through their own use-cases, they are welcome to do so, and can do so by replacing the xrdp-selinux RPM. Shops which don't want to user SELinux, for whatever reason, do not have to install the xrdp-selinux RPM. AAUI, that's from the Fedora packaging guidelines.
Thanks for your changes, and the work youve put into this. I'll have a good look and a think when I've got a bit more time than I have today.

I've got two significantly larger comments in addition to the minor one above.
The first is that AppArmor support is not supported on all our target platforms (some Linux, but also notably FreeBSD), and so needs to be enabled at compile time. That's pretty simple, and I even worked out a patch for it (attached).
patch.txt
The second is a bit more of a problem, possibly a showstopper. I was looking at substituting variables in the apparmor.d instfiles. The substitution is easy enough, and renaming the files to match whatever sbindir is set to is also doable. The problem is that the files themselves are way too specific to Debian/Ubuntu in their current form.
There's a bunch of stuff in there that we have no real control over, including but not limited to:-

Paths to X servers
Paths to TLS cert + key
Paths to stuff in user XDG_DATA_HOME.
Stuff that the X server does with dbus.

I think these are going to have to be factored out into Distro-specific files somehow (which will not be maintained by us), and it's not at all clear to me how we can do that.

Re AppArmor support on target platforms: Is a configure option really necessary? The AppArmor proc-file check only occurs if HAVE_SYS_PRCTL_H and PR_SET_NO_NEW_PRIVS are defined; presumably this will only be the case on Linux. On Linux systems that are not using AppArmor, the g_file_open_ro() call will fail harmlessly.
(Also, --enable-apparmor would imply that xrdp is using the AppArmor backend library, which is way more integration than I think either of us want)
Re distro-specific bits, yes---the profiles I've submitted are particular to Debian/Ubuntu, as that is what I'm able to provide. Generalizing them to cover other distros will need contributions from those users.
The bits that are outside of our control should, in theory, be addressed by the #include <abstractions/...> lines. I made use of those as much as I could, but there were still a few required permissions that they did not cover.
However, while the profiles may not be as simple as they ought to be, the fact that they (AFAIK) exhaustively list the permissions required for the programs to run is useful. It means that a packager need only delete permissions that are made redundant by newer abstractions (or edit paths on existing permissions to match distro conventions) instead of having to hunt for new, unknown permissions. And permissions relating to XDG_DATA_HOME and DBus shouldn't need to be touched at all, as those elements are standardized across distros by freedesktop.org.
And of course, if users contribute details of the modifications that are needed to adapt the profiles to their systems, then those can be rolled in so the profiles are ready to use out-of -the-box. To give a simple example, where Debian/Ubuntu use /etc/ssl/certs/ssl-cert-snakeoil.pem, another distro might use /etc/certs/snakeoil.pem. That wouldn't even need to be substituted; the profile could safely grant read access to both. (It's unlikely that any system would use both directories, and desire to limit access to only one.)

I believe the configure option is necessary. We've made a decision as a project to make such things explicit, so that xrdp -v is always informative, and so that distros don't have to pollute their packaging scripts by removing unnecessary stuff for them.  AppArmor is by no means a universally supported LSM.
I'll try to be a little bit clearer about my profile concerns. We really don't have the effort available on this project to spend time fixing AppArmor profiles which aren't quite right for users who have made changes to their systems without having the competence to consider the consequences. We've all been there as users ourselves, and I'm happy to help many newbies here (as my posting record will testify).  It is however important that anything we merge here doesn't impact our existing maintenance burden, which we are actively trying to reduce at the moment (with over 300 outstanding issues).
It follows that anything we ship has to be bullet-proof, either because it's been fully tested by us, or because the distros have decided it's a feature they're happy to enable and make bulletproof themselves.
Please don't misunderstand me - I think what you're doing here is a great addition.
The generalisations will need to be made before we can ship any live profiles. I'm happy for us to ship an example profile for Ubuntu, but I think even the one we have at the moment is too fragile for this.

That's a well-considered post - thanks.
Configuration options; I'm happy with 1). I'd considered 2) as well myself, but discounted it for precisely the reasons you suggest. I find interposing a shell script for an executable is a really handy debugging technique.
As regards the profiles, what you suggest is fine, but the README needs to go at the top-level I think so that it's more prominent. It can probably also be linked from the project README.md so it's findable from the description on Github. Maybe a README.apparmor.md?
I accept the chicken-and-egg problem is a real one. I'm less sure than you are about the benefits or possibilities of collaboration, but then I'm also less knowledgeable about AppArmor in general!
I'm very happy to work with you to get something in here. I've got a few family commitments at the moment which are going to take up quite a lot of my free time. Please don't take any long periods of silence on my part as a lack of interest.

All right, I think we have a way forward. Please let me know if any of my understanding below is at variance with yours.

I'll remove the AppArmor /proc interface code, and implement a sesman.ini configuration option that will allow users to explicitly disable the use of NNP when invoking the X server.
I'll write up a README.apparmor.md file explaining the development situation with the AppArmor profiles. As I plan on using the profiles regularly in my own site deployments, it'll probably include a request to ping me on related PRs.
I can also update the README.md file to link to the aforementioned. If you have any particular wording in mind, let me know.
Here is a draft Win32 implementation for g_file_open_ex() I've put together (needed so that g_file_open_ro() doesn't just fail on Windows). This comes purely from eyeballing Microsoft docs, and I have no way of testing it, so please let me know if this is at least passable:int
g_file_open_ex(const char *file_name, int aread, int awrite,
               int acreate, int atrunc)
{
#if defined(_WIN32)
    DWORD aflags = 0;
    DWORD dispos = 0;

    if (aread)
    {
        aflags |= GENERIC_READ;
    }
    if (awrite)
    {
        aflags |= GENERIC_WRITE;
    }
    if (acreate)
    {
        dispos = atrunc ? CREATE_ALWAYS : OPEN_ALWAYS;
    }
    else
    {
        dispos = atrunc ? TRUNCATE_EXISTING : OPEN_EXISTING;
    }

    return (int)CreateFileA(file_name, aflags,
                            FILE_SHARE_READ | FILE_SHARE_WRITE,
                            0, dispos, FILE_ATTRIBUTE_NORMAL, 0);
#else
    ...

I accept the chicken-and-egg problem is a real one. I'm less sure than you are about the benefits or possibilities of collaboration, but then I'm also less knowledgeable about AppArmor in general!

"Collaboration" may have been overselling it a bit, but the key point is that interested newcomers build upon the work that has already been done, rather than [feel they have no choice but to] start from scratch.

I'm very happy to work with you to get something in here. I've got a few family commitments at the moment which are going to take up quite a lot of my free time. Please don't take any long periods of silence on my part as a lack of interest.

Understood; I have my own "extracurriculars" as well. I'll need some more time to get all this together, but it'll come---this is ultimately my own itch I'm scratching!

I don't think you need to spend time to support Win32. See also Platform Support Tier for the status of Win32. You can focus on Linux (and BSD) rather than taking effort for Win32.

@metalefty: Understood; thanks for the heads-up. I'll keep my changes POSIX-only.

@iskunk - that all sounds fine to me, and along the lines I'm thinking.
You'll need to add a commented-out setting for your variable to sesman/sesman.ini.in. There's also a man page in  docs/man/sesman.ini.5.in where you can add more detail - just use the examples which are already there, and feel free to as any questions you may have.
Thanks.

@matt335672, of course. Here is an early draft for those; let me know if this looks OK:
diff --git a/docs/man/sesman.ini.5.in b/docs/man/sesman.ini.5.in
index 366ecfad..ea6694da 100644
--- a/docs/man/sesman.ini.5.in
+++ b/docs/man/sesman.ini.5.in
@@ -293,6 +293,15 @@ To keep compatibility, the following aliases are also available.
 If set to \fB1\fR, \fBtrue\fR or \fByes\fR, require group membership even
 if the group specified in \fBTerminalServerUsers\fR doesn't exist.

+.TP
+\fBXorgNoNewPrivileges\fR=\fI[true|false]\fR
+Only applicable on Linux. If set to \fB0\fR, \fBfalse\fR or \fBno\fR, do
+not use the kernel's \fIno_new_privs\fR restriction when invoking the Xorg
+X11 server. The use of \fIno_new_privs\fR is intended to prevent issues due
+to a setuid Xorg executable. However, if a kernel security module (such as
+AppArmor) is used to confine xrdp, \fIno_new_privs\fR may interfere with
+transitions between confinement domains.
+
 .SH "X11 SERVER"
 Following parameters can be used in the \fB[X11rdp]\fR, \fB[Xvnc]\fR and
 \fB[Xorg]\fR sections.
diff --git a/sesman/sesman.ini.in b/sesman/sesman.ini.in
index 278224a1..bc7aad06 100644
--- a/sesman/sesman.ini.in
+++ b/sesman/sesman.ini.in
@@ -38,6 +38,12 @@ RestrictOutboundClipboard=none
 ;   yes: an alias of all
 RestrictInboundClipboard=none

+; On Linux systems, the Xorg X11 server is normally invoked using
+; no_new_privs to avoid problems if the executable is suid. This may
+; interfere with the use of security modules such as AppArmor. Leave this
+; unset unless you need to disable it.
+#XorgNoNewPrivileges=true
+
 [Sessions]
 ;; X11DisplayOffset - x11 display number offset
 ; Type: integer

That looks fine to me.
You can preview what the manpage will look like with man /path/to/sesman.ini.5.in, just to check the formatting looks OK. I haven't done that myself.

Due to the ongoing restructuring of sesman, the AppArmor profiles previously presented here will need significant updates. For now, I'd like to get in just the code changes, which I believe everyone here was amenable to. I've rebased my changes to the current tree, and re-worked the commit chain of this PR accordingly. I'll submit new AppArmor profiles for consideration in a future PR, once xrdp has stabilized. Please let me know if there are any issues.

On a related note, a couple of questions for @matt335672:

Given that the way sesman starts the user session is being changed, along with many other things, would it be possible to address the issue previously noted in this PR ("There is one major hole in these AppArmor profiles...") ?
The gist of it is: Don't set up the environment and then execute startwm.sh directly, because the parent process could be under the control of an attacker who can set their own PATH, LD_PRELOAD, program args, etc.---and any AppArmor permission that allows a process the unconfined invocation of a shell script can be leveraged to run an arbitrary, possibly attacker-supplied binary. Instead, execute some helper program that doesn't depend on any environment variables, and takes no program args. That helper, in turn, then does the environment setup, and executes startwm.sh/DefaultWindowManager.
The AppArmor profile can specify a permission only allowing unconfined execution of the helper with a scrubbed environment. So even though this helper program remains an "escape hatch" to the restrictions imposed on sesman sesexec (?), there's much less of a way for an attacker to abuse it for their own ends.

With all the reworking of how PAM is handled, can we now expect both systemd sessions and pam_mkhomedir/fscrypt/etc. to work? (I specifically had an issue with fscrypt that boiled down to pam_open_session() being called in a different process from previous PAM calls, and noted that this behavior was implemented due to the earlier systemd issue. I'm hoping the tug-of-war got resolved.)

Hi @iskunk
As I've mentioned in another PR, CI is now fixed and requires a rebase to get working.
I'll address your questions first.

The way sesexec uses PAM is completely standard. All PAM calls related to session management are now made from one process. The only exception is when a user reconnects to a session. A new PAM stack is used to authenticate and authorize the user, and then that PAM stack is thrown away because there's one already in place for the session.
I can't see how an additional process can be used to prevent the attack you describe. sesexec would need to pass the name of sesman.ini to the additional process (this is a runtime setting), and this can be crafted to allow a redirection to any file of the attacker's calling. Am I misunderstanding something?

Rebased as requested. (Thanks for straightening out those CI failures!)

Bravo! I hope to try making fscrypt work with xrdp again. (Since pam_mkhomedir was a known issue, I'm assuming xrdp now knows not to touch the user homedir until pam_open_session() returns)
Yes, an attacker-chosen sesman.ini would be bad. Would it be reasonable to limit the file to somewhere under XRDP_CFG_PATH, or does it need to be completely arbitrary? (sesman/sesexec itself would be limited in where it could read a config file from by AppArmor anyway)

pam_open_session() is called as root before any of the xrdp sub-processes attempt to access $HOME for the user. The code is in session_start_wrapped(). pam_open_session is called from auth_start_session().
Yes, that would be reasonable, although in general this is a difficult (or even impossible) thing to achieve because of symlinks. Could you expand a bit more on what you're suggesting? It's a pretty good time to change this interface,before next major release.

Yes, that would be reasonable, although in general this is a difficult (or even impossible) thing to achieve because of symlinks. Could you expand a bit more on what you're suggesting?

The idea would be for the helper program to ensure that the config-file path starts with e.g. /etc/xrdp/ and contains no /../ elements. The AppArmor-confined sesman process would have no write access to /etc/xrdp/ nor its parents---even though the process is running as root. So if any path matching the criteria traverses symlinks, then that is presumably because the sysadmin put the symlinks there, not the attacker.

Very happy with this (as already discussed), but we could do with testing your g_file_open() changes.

Gladly! I've rolled in your test code to my first commit, and confirmed that it passes. (I don't have much to add there, not least as these functions are used everywhere, even in the testing code itself...)

The idea would be for the helper program to ensure that the config-file path starts with e.g. /etc/xrdp/ and contains no /../ elements. The AppArmor-confined sesman process would have no write access to /etc/xrdp/ nor its parents---even though the process is running as root. So if any path matching the criteria traverses symlinks, then that is presumably because the sysadmin put the symlinks there, not the attacker.

So to summarise:-

If config file path starts with '/' it has to start with $XRDP_CFG_PATH/. Otherwise it's a relative path to $XRDP_CFG_PATH.
config file path has no reason to contain '/../'

We can simplify this to only allowing relative paths, and not allowing '..' to appear in the config file path.
I'm still somewhat concerned about a helper program setting a default environment. In general, by the time we get to this stage, the environment will have been set largely by PAM (or other) calls. I can't see any way to generalise this.
The restrictions you've mentioned above for the config could be placed on the startwm.sh invocation instead. Doesn't that cover most of your concerns?
I'm going to merge this, by-the-way. Thanks again. I think we can continue the above conversation here.

So to summarise:-

If config file path starts with '/' it has to start with $XRDP_CFG_PATH/. Otherwise it's a relative path to $XRDP_CFG_PATH.

config file path has no reason to contain '/../'

We can simplify this to only allowing relative paths, and not allowing '..' to appear in the config file path.

Pretty much, yes. (Though interpreting a relative config-file path as relative to $XRDP_CFG_PATH instead of the current directory may be unexpected by the user.)

I'm still somewhat concerned about a helper program setting a default environment. In general, by the time we get to this stage, the environment will have been set largely by PAM (or other) calls. I can't see any way to generalise this.

Yes, a necessary aspect to this is that the helper needs to throw away whatever environment it gets (or more specifically, when it is invoked by sesman/sesexec, an AppArmor rule will scrub the environment beforehand), so it will need to set up the user environment itself.
Is there not a good way to recreate the environment given by pam_env.so et al. but in a separate, user-owned process? I was afraid that might be the case...

The restrictions you've mentioned above for the config could be placed on the startwm.sh invocation instead. Doesn't that cover most of your concerns?

That approach can also work, since the AppArmor rule can be written to allow (direct) invocation of the script with a scrubbed environment. But then startwm.sh (or whatever other default_wm is configured) needs to set up the environment itself, similarly from scratch. Would that approach be preferable?

I'm going to merge this, by-the-way. Thanks again. I think we can continue the above conversation here.

Much obliged :-)  I should have done this (submitted the code changes and left the AA profiles pending) a long time ago.

I don't think there's a good way to reconstruct the PAM environment in another process. I looked into this in quite some detail when I was constructing the updated architecture. PAM implementations rather assume that everything is happening in the one process.
So if sesexec is compromised, the best we can do is contain the damage as much as possible.
Can restricting the window manager script to be under $XRDP_CFG_PATH be done by AppArmor directly? I don't suppose you know what other login managers do in this regard?

Ensuring that the wm script is in the proper directory is doable, but it doesn't get you much, unfortunately. Even if the script is squeaky-clean, it is still a typical shell script, and is thus prone to muckery like the following:

Set PATH=/tmp/evilbin:$PATH;
Place a few custom programs in this directory, all identically evil: [, test, grep, etc.;
Execute the script, and wait for it to run your evil program.

Unless a shell script goes to the trouble of guarding against this---and it's not even clear to me how feasible that is, given the complexity of the shell environment---it's a sitting duck for this line of attack. (And that's not even getting into what you can do with shell functions, LD_PRELOAD, etc.)
That's why scrubbing a potentially compromised environment is critical. Sesexec may run the wm script as root (because root could legitimately be logging in, questionable as that is), and while sesman/sesexec can be confined under AppArmor (limiting what an attacker can do, even as root), the wm script is not. And if the attacker can make the script walk into their chosen program, as root, then it's game over.
There may not be a good solution to this, that doesn't break PAM functionality in one way or another.
The closest parallel I can think of is OpenSSH, with its privilege separation and sandboxing mechanisms. (If you need a refresher, this article presents a good general overview IMO. Not to say that those mechanisms have always been impregnable, of course.)
The startwm.sh issue aside, I think it would be good to officially adopt the Debian practice of running the xrdp daemon as an unprivileged user. Since that daemon is what services the external network connection, the basis of a similar privilege-separation strategy is already in place. It just needs to be taken further.

At present, the 'WM script' can be any executable - it doesn't have to be a script. The code in sesexec just execs whatever it's given.
The problem is, how do you clean up an environment that's potentially compromised at that point? I think we agree that's not solveable in general, but for specialist environments it very much is. I agree that s shell script is not as well suited to this as a specific executable would be. Those environments can provide a suitable executable which knows what the environment would be, and can enforce it before running the script.
Some distros are moving towards using systemd --user to start the whole desktop. If this catches on, the executable can be systemctl, or something that calls it.
The Debian practice is on my short-term TODO list. We've already spoken about this internally.

A security-critical environment could forgo the standard PAM environment setup, do the AppArmor environment scrubbing when executing default_wm, and then have that be a special program (it could be a script, no big deal when the env is clean) that sets up the environment from scratch. But that's too oddball from an administrative perspective for me to expect more than a handful of users to ever do it.
So, while I'll give up on the idea of secure execution of default_wm for the masses, protecting sesman by battening down the xrdp daemon seems like a good fallback position. Re the Debian practice TODO: :+1:


Bug: hyprbars status is abnormal

When I use the hyprbars plugin, dragging window's content often automatically enters the drag mode, like dragging hyprbars.

can you find a way to reproduce this?

can you find a way to reproduce this?

After opening it, dragging the selected text within the open program window will trigger window dragging.
This problem continues to occur in my system, and I don't know if it can be replicated by others.
Till now, I don't know what I should do to solve this bug?

Recently, it has been found that there should be no obvious pattern when entering this state.
It is more obvious that when a form enters this state:

This form will not return to its original layout.
When the mouse moves past other forms, there is a high probability that the program will also enter this state.


Render HTML tags containing uppercase letters

Timeline and article view don't render cursive tags containing capital I (and probably others). Accepting them is probably incorrect behavior, but fuzziness would look better on the user end.
As seen in this feed: https://www.gamedeveloper.com/rss.xml

https://www.gamedeveloper.com/business/4th-annual-impy-award-noms-showcase-the-wondrous-world-of-dreams

I’m betting we strip out lowercase but not uppercase. Uppercase is pretty rare these days — but clearly it’s still a thing.


Option to delay rule evaluations

Proposal
With out-of-order ingestion, now time series can get old data anytime. There could be recording rules that need to be re-calculated for a timestamp because they got new samples. But it is also possible that you can identify a set of rule groups that tend to get delayed samples (especially when coupled with the remote-write receiver). In this case, having the ability to delay the evaluation of rule groups can keep the recording rule results more accurate.
The proposal is to add a new field evaluation_delay to the rule group. And let's say the delay is d, whenever the rule has to evaluate for time now(), it would just evaluate for time now()-d and produce samples for that time.
This is something done in Mimir and works well there. A reference implementation of how it will look in Prometheus is here https://github.com/grafana/mimir-prometheus/pull/155/.
cc @roidelapluie @beorn7 @juliusv

We could wait for some time and see if the community asks for it.

Yup, either is ok with me.

This also could help with the ingestion delay issue discussed at the dev summit last April (search for "ingestion delay" to find the relevant section).
It's not a perfect solution (and the discussion at the dev-summit suggested there might not be one), but depending on your realtime requirements, it might actually be a good practice to add a bit of delay to most rule groups.

That makes sense. I used offset in PromQL queries in the past to simulate this. I propose we validate that OOO window is larger than the delay.

I propose we validate that OOO window is larger than the delay.

I think we should not validate it, because it gets complicated quickly. For example, even without OOO window set, you can still get samples up to 1hr old that is not out-of-order. And some backfilling could be going on behind the scenes. So I would not add restrictions.

The restriction is to make sure that we can ingest the result in the tsdb.

The restriction is to make sure that we can ingest the result in the tsdb.

Oh yeah, did not think about that. max_delay=max(1h, OOO window).

Hello from the bug scrub.
We believe this has been implemented by https://github.com/prometheus/prometheus/pull/14061.
Closing this issue, please follow up if the PR linked above has not fully resolved the issue.


Update names and descriptions for integrations

Description
Switches names to the official product names instead of abbreviations, and updates the descriptions to clarify what the integration actually processes. Also found some logos without transparent backgrounds that were replaced and optimized.
I tried my best to use the product names from official documentation. Main concern is that WAF inconsistently switches between being called "AWS WAF" and "AWS Web Application Firewall", I went with the more verbose one.
Before:

After:

Issues Resolved
Closes #1461
Check List

[ ] New functionality includes testing.

[ ] All tests pass, including unit test, integration test and doctest

[ ] New functionality has been documented.

[ ] New functionality has javadoc added
[ ] New functionality has user manual doc added

[X] Commits are signed per the DCO using --signoff

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
For more information on following Developer Certificate of Origin and signing off your commits, please check here.

Looks good!


Radio buttons in line with other boxes

Request

No! Bad

Will implement for testing purposes.  Simple fix.


Constructor implementation

The README.md mentions a constructor pattern
var context = LD( { ... etc. } );
var doc = context( data );

that is not actually implemented. This pull supplies the missing constructor pattern.

Thanks!


fix(runtime-binding-generator): address the changes in the class name format

merge into revert, jenkins should pass there


Unsoundness of Buffer::from_iter

The source of unsoundness
Hi, we are the Rust researchers from SunLab. Recently, we are trying to test our static analysis tool and find the potential unsound function in the package of arrow-buffer:
https://github.com/apache/arrow-rs/blob/90bc5ec96b5ae5162f469f9784dde7b1a53a5bdd/arrow-buffer/src/buffer/immutable.rs#L417-L432
In line 429, when the mutable pointer is cast to generic type, it is actually casting from u8 to any-aligned type which could create a misaligned pointer. However, it seems that the programmers are also aware of the bugs in the test case:
https://github.com/apache/arrow-rs/blob/90bc5ec96b5ae5162f469f9784dde7b1a53a5bdd/arrow-buffer/src/buffer/scalar.rs#L224-L231
Here, u8 is cast to i32 and create a misaligned pointer and panic occurs.
We consider that it should not happen in safe API anyway based on the safety requirement of ptr.write(). The problem could be fixed by passing the layout of element to allocate the memory.
We would love to have more discussion, and please correct if we are wrong.

it is actually casting from u8 to any-aligned type which could create a misaligned pointer

MutableBuffer uses an aligned allocator, with an alignment exceeding that of any ArrowNativeType

@tustvold thanks for the response. Then, why does it still panic?

Because the Buffer::slice which comes after in the test is shifting it so that Buffer is no longer aligned, but unlike MutableBuffer, Buffer has no alignment restrictions so this is safe

Fair enough. Thanks!

Yes. I just realized these two lines after discussion with you :joy:
https://github.com/apache/arrow-rs/blob/90bc5ec96b5ae5162f469f9784dde7b1a53a5bdd/arrow-buffer/src/buffer/mutable.rs#L72-L73

I've taken the liberty of updating the issue title to rephrase this into an enhancement proposal. I think this should be relatively straightforward, and less unsafe is always a good thing, the major task would be making sure it doesn't regress anything


Update Flash_ops.c to enable direct communication with the SPI FLASH (IDFGH-2085)

This code enable the flash to be read and return it internal registers, extreme usefull to know flash id, flash version, flash vendor, flash size, flash serial number, and so many others info available from the flash manufacturer.
Example usage to return a valid flash ID:
uint8_t flash_unique_id[9] = {0};
// Get flash unique id 0x4b
uint8_t command[13] = {0x4b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
// Get JEDEC ID 0x9f
//uint8_t command[13] = {0x9f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
// Get Manufacturer ID 0x90
//uint8_t command[13] = {0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t response[13];
spi_flash_send_cmd(sizeof(command), command, response);
Simple, and can send any command from the flash vendor.

@filzek Thanks for the contribution.

I will provide more codes but I need to port it to latest if first, so it need some corrections, as I finish I will request some new pushes.

@filzek Please note that the flash_ops.c contains the legacy SPI flash code; there is a new driver, with APIs in esp_flash.h. It relies on a chip-specific driver in spi_flash_chip_driver.h.
If you are implementing support for a new SPI flash chip, you can define a driver for it, see spi_flash_chip_gd.c, spi_flash_chip_issi.c, etc.

I will check tomorrow, as legacy it does work for any native flash (app) on esp32.
I will try to use the new driver code to read the I'd from flash, and cross check the results and post it tomorrow.
I did not find any example on read flash Id for the current spi flash on esp32, but will try to run it.

@igrr  I try to run the code:
esp_flash_t * internnal_flash_chip;
uint32_t id, size;
esp_flash_read_id(&internnal_flash_chip, &id);
esp_flash_get_size(&internnal_flash_chip, &size);
printf("Flash ID %08x detected size %d bytes\n", id, size);
but it only returns 0000000..
I did not understant quite how to use the code to read the internal flash id and its size, so, no luck at all.
Can you clarify steps?

@igrr I try to run the code:
esp_flash_t * internnal_flash_chip;
uint32_t id, size;
esp_flash_read_id(&internnal_flash_chip, &id);
esp_flash_get_size(&internnal_flash_chip, &size);
printf("Flash ID %08x detected size %d bytes\n", id, size);
but it only returns 0000000..
I did not understant quite how to use the code to read the internal flash id and its size, so, no luck at all.
Can you clarify steps?

we need to read the internal ESP32 flash id.
all attemp we tried based on esp_flash_read_id fail.
Our legacy code runs smooth and without any problem, and ID match to direct reading flash.

 Thank you for your submission, we really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.You have signed the CLA already but the status is still pending? Let us recheck it.

 Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.You have signed the CLA already but the status is still pending? Let us recheck it.

@filzek if you initialize as esp_flash_t * internnal_flash_chip;, the function should be esp_flash_read_id(internnal_flash_chip, &id);. It will return the ture value.

@filzek Thanks for your suggestion with flash_ops, we are still maintaining it. What you 've done is meaningful, but if you use our new api, you will get better experience.

I have tried to run the code but error is deployed:
esp_flash_t * internnal_flash_chip;
uint32_t id, size;
esp_flash_read_id(internnal_flash_chip, &id);
esp_flash_get_size(internnal_flash_chip, &size);

error: 'internnal_flash_chip' is used uninitialized in this function [-Werror=uninitialized]
esp_flash_read_id(internnal_flash_chip, &id);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
so, still cant move to the new api to read the true ID of internnal flash, please advise the working code.

@filzek Thanks for your suggestion with flash_ops, we are still maintaining it. What you 've done is meaningful, but if you use our new api, you will get better experience.

esp_flash_read_id  returns a WRONG Flash ID. The function need to READ THE REAL FLASH ID from the IC!

For example on a true board:
using  esp_flash_read_id
Initialized internnal_flash_chip, size=8192 KB, ID=0xc84017
flash_id: [13123607]
using the API we have develop
REAL FLASH ID:<PHONE_NUMBER>701032
when remove the flash and external read it, the flash is same as our api read:<PHONE_NUMBER>701032
so, why the esp_flash_read_id doesnt work as intent?


Localizations didn't work inside GridView.builder ?

Steps to Reproduce

Download project from my repo https://github.com/EArminjon/flutter-context-issue
Execute flutter run
Go to your phone settings and change the phone locale.
Go back to your app and see that the top section is not updated.
Do a hot reload.
Top section is updated...

Expected results:
Would see the top section refreshed as the app bar and the bottom section.
Actual results:
Top section is not refresh.

Code sample

My repo contain more file useful for the test. (dependencies, l10n.yaml, arb files)
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';

void main() {
  runApp(const App());
}

class CardUsingBuilderContext extends StatelessWidget {
  const CardUsingBuilderContext({super.key});

  @override
  Widget build(BuildContext context) {
    return GridView.builder(
      physics: const NeverScrollableScrollPhysics(),
      gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
        crossAxisCount: 2,
        // comps + default card margin 87 + 8
        mainAxisExtent: 95,
        mainAxisSpacing: 16,
        crossAxisSpacing: 16,
      ),
      cacheExtent: 0,
      shrinkWrap: true,
      padding: const EdgeInsets.symmetric(horizontal: 16),
      itemCount: 4,
      itemBuilder: (BuildContext context, int index) {
        return Card(
          child: Center(
            child: Text(AppLocalizations.of(context)!.test),
          ),
        );
      },
    );
  }
}

class CardUsingWidgetContext extends StatelessWidget {
  const CardUsingWidgetContext({super.key});

  @override
  Widget build(BuildContext context) {
    return GridView.builder(
      physics: const NeverScrollableScrollPhysics(),
      gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
        crossAxisCount: 2,
        // comps + default card margin 87 + 8
        mainAxisExtent: 95,
        mainAxisSpacing: 16,
        crossAxisSpacing: 16,
      ),
      cacheExtent: 0,
      shrinkWrap: true,
      padding: const EdgeInsets.symmetric(horizontal: 16),
      itemCount: 4,
      itemBuilder: (BuildContext _, int index) {
        return Card(
          child: Center(
            child: Text(AppLocalizations.of(context)!.test),
          ),
        );
      },
    );
  }
}

class AppSettings extends ChangeNotifier {
  bool darkMode;

  AppSettings({
    this.darkMode = false,
  });

  void useDarkMode(bool value) {
    darkMode = value;
    notifyListeners();
  }
}

class App extends StatelessWidget {
  const App({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      localizationsDelegates: const [
        AppLocalizations.delegate,
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
      ],
      supportedLocales: const <Locale>[
        Locale('en'),
        Locale('fr'),
      ],
      home: Builder(
        builder: (context) {
          return Scaffold(
            appBar: AppBar(title: Text(AppLocalizations.of(context)!.test)),
            body: Column(
              children: const <Widget>[
                // Broken
                CardUsingBuilderContext(),
                Divider(),
                // Working
                CardUsingWidgetContext(),
              ],
            ),
          );
        },
      ),
    );
  }
}

Logs

No logs

No warnings

[✓] Flutter (Channel stable, 3.3.8, on macOS 12.6.1 21G217 darwin-arm, locale fr-FR)
    • Flutter version 3.3.8 on channel stable at /Users/earminjon/fvm/versions/3.3.8
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 52b3dc25f6 (4 weeks ago), 2022-11-09 12:09:26 +0800
    • Engine revision 857bd6b74c
    • Dart version 2.18.4
    • DevTools version 2.15.0

[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.0)
    • Android SDK at /Users/earminjon/Library/Android/Sdk
    • Platform android-33, build-tools 33.0.0
    • ANDROID_HOME = /Users/earminjon/Library/Android/Sdk
    • Java binary at: /Users/earminjon/Library/Application Support/JetBrains/Toolbox/apps/AndroidStudio/ch-0/213.7172.25.2113.9123335/Android Studio.app/Contents/jre/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 11.0.13+0-b1751.21-8125866)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 14.0.1)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 14A400
    • CocoaPods version 1.11.3

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2021.3)
    • Android Studio at /Users/earminjon/Library/Application Support/JetBrains/Toolbox/apps/AndroidStudio/ch-0/213.7172.25.2113.9123335/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 11.0.13+0-b1751.21-8125866)

[✓] IntelliJ IDEA Ultimate Edition (version 2022.2.3)
    • IntelliJ at /Users/earminjon/Applications/JetBrains Toolbox/IntelliJ IDEA Ultimate.app
    • Flutter plugin version 71.0.5
    • Dart plugin version 222.4345.14

[✓] IntelliJ IDEA Ultimate Edition (version 2022.2.3)
    • IntelliJ at /Users/earminjon/Library/Application Support/JetBrains/Toolbox/apps/IDEA-U/ch-0/222.4345.14/IntelliJ IDEA.app
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart

[✓] Connected device (3 available)
    • sdk gphone64 arm64 (mobile) • emulator-5554 • android-arm64  • Android 13 (API 33) (emulator)
    • macOS (desktop)             • macos         • darwin-arm64   • macOS 12.6.1 21G217 darwin-arm
    • Chrome (web)                • chrome        • web-javascript • Google Chrome 107.0.5304.121

[✓] HTTP Host Availability
    • All required HTTP hosts are available

• No issues found!

At the end of the video I do a hot reload. The top section is refreshed after that.
untitled.webm

Thanks for the report @EArminjon
From the code you shared, I don't see difference between CardUsingWidgetContext and CardUsingBuilderContext class, as the code seems to be same in both. Can you provide code in CardUsingWidgetContext that works as expected as compared to CardUsingBuilderContext ?

Thanks for the report @EArminjon From the code you shared, I don't see difference between CardUsingWidgetContext and CardUsingBuilderContext class, as the code seems to be same in both. Can you provide code in CardUsingWidgetContext that works as expected as compared to CardUsingBuilderContext ?

Code same, but Text widget inside didn't use the same context.

Thanks for the update. Using the repo provided above, seeing the same behavior as reported.

 stable, master flutter doctor -v
[✓] Flutter (Channel stable, 3.3.9, on macOS 12.2.1 21D62 darwin-x64, locale
    en-GB)
    • Flutter version 3.3.9 on channel stable at
      /Users/dhs/documents/fluttersdk/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision b8f7f1f986 (12 days ago), 2022-11-23 06:43:51 +0900
    • Engine revision 8f2221fbef
    • Dart version 2.18.5
    • DevTools version 2.15.0

[!] Xcode - develop for iOS and macOS (Xcode 12.3)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    ! Flutter recommends a minimum Xcode version of 13.
      Download the latest version or update via the Mac App Store.
    • CocoaPods version 1.11.2

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] VS Code (version 1.62.0)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.21.0

[✓] Connected device (5 available)
    • SM G975F (mobile)       • RZ8M802WY0X • android-arm64   • Android 11 (API 30)
    • Darshan's iphone (mobile)  • 21150b119064aecc249dfcfe05e259197461ce23 •
      ios            • iOS 14.4.1 18D61
    • iPhone 12 Pro Max (mobile) • A5473606-0213-4FD8-BA16-553433949729     •
      ios            • com.apple.CoreSimulator.SimRuntime.iOS-14-3 (simulator)
    • macOS (desktop)            • macos                                    •
      darwin-x64     • Mac OS X 10.15.4 19E2269 darwin-x64
    • Chrome (web)               • chrome                                   •
      web-javascript • Google Chrome 98.0.4758.80

[✓] HTTP Host Availability
    • All required HTTP hosts are available

! Doctor found issues in 1 category.

[!] Flutter (Channel master, 3.7.0-4.0.pre.38, on macOS 12.2.1 21D62 darwin-x64,
    locale en-GB)
    • Flutter version 3.7.0-4.0.pre.38 on channel master at
      /Users/dhs/documents/fluttersdk/flutter
    ! Warning: `flutter` on your path resolves to
      /Users/dhs/Documents/Fluttersdk/flutter/bin/flutter, which is not inside
      your current Flutter SDK checkout at
      /Users/dhs/documents/fluttersdk/flutter. Consider adding
      /Users/dhs/documents/fluttersdk/flutter/bin to the front of your path.
    ! Warning: `dart` on your path resolves to
      /Users/dhs/Documents/Fluttersdk/flutter/bin/dart, which is not inside your
      current Flutter SDK checkout at /Users/dhs/documents/fluttersdk/flutter.
      Consider adding /Users/dhs/documents/fluttersdk/flutter/bin to the front
      of your path.
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 521028c808 (8 hours ago), 2022-12-07 13:46:17 -0800
    • Engine revision 67254d6e4b
    • Dart version 2.19.0 (build 2.19.0-467.0.dev)
    • DevTools version 2.20.0
    • If those were intentional, you can disregard the above warnings; however
      it is recommended to use "git" directly to perform update checks and
      upgrades.

[!] Xcode - develop for iOS and macOS (Xcode 12.3)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    ! Flutter recommends a minimum Xcode version of 13.
      Download the latest version or update via the Mac App Store.
    • CocoaPods version 1.11.2

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] VS Code (version 1.62.0)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.21.0

[✓] Connected device (5 available)
    • SM G975F (mobile)       • RZ8M802WY0X • android-arm64   • Android 11 (API 30)
    • Darshan's iphone (mobile)  • 21150b119064aecc249dfcfe05e259197461ce23 •
      ios            • iOS 14.4.1 18D61
    • iPhone 12 Pro Max (mobile) • A5473606-0213-4FD8-BA16-553433949729     •
      ios            • com.apple.CoreSimulator.SimRuntime.iOS-14-3 (simulator)
    • macOS (desktop)            • macos                                    •
      darwin-x64     • Mac OS X 10.15.4 19E2269 darwin-x64
    • Chrome (web)               • chrome                                   •
      web-javascript • Google Chrome 98.0.4758.80

[✓] HTTP Host Availability
    • All required HTTP hosts are available

! Doctor found issues in 1 category.

@thkim1011

So I've finally figured out why this doesn't rebuild on locale change. Dart seems to treat the delegate as not having been updated in your case. I've checked that the condition in
https://github.com/flutter/flutter/blob/73bb959a65243639fe19de1f9abb537ce7251dc3/packages/flutter/lib/src/widgets/sliver.dart#L732
evaluates to false.
It seems like modifying the build function so that its itemBuilder is a different function on locale change solves this issue. For example,
  @override
  Widget build(BuildContext context) {
    AppLocalizations localizations = AppLocalizations.of(context)!;
    return GridView.builder(
      physics: const NeverScrollableScrollPhysics(),
      gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
        crossAxisCount: 2,
        // comps + default card margin 87 + 8
        mainAxisExtent: 95,
        mainAxisSpacing: 16,
        crossAxisSpacing: 16,
      ),
      cacheExtent: 0,
      shrinkWrap: true,
      padding: const EdgeInsets.symmetric(horizontal: 16),
      itemCount: 4,
      itemBuilder: (BuildContext context, int index) {
        return Card(
          child: Center(
            child: Text(localizations.test),
          ),
        );
      },
    );
  }

so that your delegate is forced to update (as it uses a different localizations on each rebuild).
Now I'm not exactly convinced that this is the expected behavior, as I would expect itemBuilder to be distinct function objects on each call to build, so I'll look into what I can do here.

I think I'll close this as this is just the behavior of Flutter. If there aren't any changes in the itemBuilder it won't rebuild.


curl https:// works fine, but bindle search does not

So I have an interesting setup where I have both bindle and nginx set up with the same TLS certificate.
When TLS is disabled, bindle can reach the bindle server and query its search endpoint. However when TLS is enabled, only curl can query the search endpoint, but bindle returns the error "frame with invalid size".
Here's the nginx config without TLS (note that certain lines are commented out, and the proxy_pass is forwarding to http:
# BINDLE
server {
        listen      8080 http2;
        server_name bindle.f1sh.ca;
        server_name_in_redirect off;
        port_in_redirect off;
        #ssl_certificate /etc/nginx/ssl/bindle.crt;
        #ssl_certificate_key /etc/nginx/ssl/bindle.key;
        #ssl on;
        location / {
                proxy_set_header Host $host;
                proxy_set_header X-Forwarded-For $remote_addr;
                proxy_redirect off;
                proxy_pass http://<IP_ADDRESS>:8080;
                client_max_body_size 128m;
        }
}

/usr/local/bin/bindle-server --config-path /usr/local/etc/bindle/bindle.toml --directory /usr/local/lib/bindle --keyring /usr/local/etc/bindle/keyring.toml --signing-keys /usr/local/etc/bindle/signing_keys.toml.
$ bindle --server http://bindle.f1sh.ca:8080/v1 search
query = ""
strict = true
offset = 0
limit = 50
total = 0
more = false
yanked = false
invoices = []

With TLS (tls-related config is uncommented, and proxy_pass is now passing via the https scheme):
# BINDLE
server {
        listen      8080 http2;
        server_name bindle.f1sh.ca;
        server_name_in_redirect off;
        port_in_redirect off;
        ssl_certificate /etc/nginx/ssl/bindle.crt;
        ssl_certificate_key /etc/nginx/ssl/bindle.key;
        ssl on;
        location / {
                proxy_set_header Host $host;
                proxy_set_header X-Forwarded-For $remote_addr;
                proxy_redirect off;
                proxy_pass https://<IP_ADDRESS>:8080;
                client_max_body_size 128m;
        }
}

/usr/local/bin/bindle-server --config-path /usr/local/etc/bindle/bindle.toml --directory /usr/local/lib/bindle --keyring /usr/local/etc/bindle/keyring.toml --signing-keys /usr/local/etc/bindle/signing_keys.toml --tls-cert /usr/local/etc/bindle/bindle.crt --tls-key /usr/local/etc/bindle/bindle.key
$ bindle --server https://bindle.f1sh.ca:8080/v1 search
Error creating request

Error trace:
	1: error sending request for url (https://bindle.f1sh.ca:8080/v1/_q): http2 error: protocol error: frame with invalid size
	2: http2 error: protocol error: frame with invalid size
	3: protocol error: frame with invalid size

But with curl:
$ curl https://bindle.f1sh.ca:8080/v1/_q
query = ""
strict = true
offset = 0
limit = 50
total = 0
more = false
yanked = false
invoices = []

This is a self-signed certificate... Not sure if that plays into this. But it was added to my ca-cert chain and both curl and bindle trust it.

This may relate to https://github.com/deislabs/bindle/pull/147.  curl negotiates HTTP/2 by default, but bindle assumes it.  Try it with the curl HTTP2 prior knowledge flag and see if it fails?

Like this?
><> curl --http2-prior-knowledge https://bindle.f1sh.ca:8080/v1/_q
query = ""
strict = true
offset = 0
limit = 50
total = 0
more = false
yanked = false
invoices = []

I was just recalling that I got a similar error when I had a proxy in front of Bindle - curl worked but the Bindle client library didn't.  I added the option to negotiate and it started working.  But I guess from your curl command that it's not that.  grin homer backing into hedge.gif

It's a good idea... Let me try enabling that flag in bindle and see how far I get.

Huh... setting
https://github.com/deislabs/bindle/blob/ab5f5a14831edbcf357c74b4985c8e57ab1e0509/src/client/mod.rs#L57
to false and recompiling worked. How odd...
><> ./target/release/bindle --server https://bindle.f1sh.ca:8080/v1 search
query = ""
strict = true
offset = 0
limit = 50
total = 0
more = false
yanked = false
invoices = []

From curl's documentation:

Tells curl to issue its non-TLS HTTP requests using HTTP/2 without HTTP/1.1
Upgrade. It requires prior knowledge that the server supports HTTP/2 straight
away. HTTPS requests will still do HTTP/2 the standard way with negotiated
protocol version in the TLS handshake.

So I'm not sure why disabling that flag would allow bindle to work in this situation. This flag should not affect HTTPS requests if I'm reading the docs correctly.
Perhaps it's a bug in reqwest's implementation of the --http2-prior-knowledge flag?

Possible relevant issue: https://github.com/seanmonstar/reqwest/issues/857


World vocoder analysis error

For one of our voices (a male voice) the World analysis script is not producing any parameters for a few of the files in the set. The recordings are originally 22kHz but I use 'ch_wave' to downsample to 16kHz. Has anybody had any problems like this? I thought maybe it had to do with the fact that the F0 sometimes goes below 71 Hz but there are still many F0 values above that minimum? I can't see anything wrong with the audio files.

Please provide some example audio files....also try using sox to downsample and extract features.

I have included two example sentences. The first one, sent1 when converted to 16kHz with ch_wave is not analysed by the extract_features_for_merlin.py script. But when I convert using sox it does produce parameter files.
However, the second one, sent2 shows the opposite problem. When I convert with ch_wave it produces parameters but when I use sox it doesn't.
I have played around with the floorF0 value in the constantnumbers.h file but it doesn't seem to help. I can't see anything wrong with the files. Of course I could just exclude the empty files from training, but I would like to understand why WORLD would be unable to produce any features.
ex.zip

This is due to clipping effect, use sox to normalise the audio files. You can check for option --norm here
I used original sampling rate as it is and first file seems okay, second file required normalization as shown below:
sox −−norm infile outfile
Configuration variables for 22khz:
if [ "$fs" -eq 22050 ]
then
nFFTHalf=1024
alpha=0.65
fi
You can chose to downsample as well:
sox --norm infile -r 16000 outfile

Great, thanks so much for helping me figure that out. Should I just run sox --norm per default?


Add generator support for FK constraint

Is your feature request related to a problem? Please describe.
The M8 framework include annotations for signaling FK on models. The annotation must generate FK constraints
Describe the solution you'd like
Add generator support for FK constraint. The implementation will lead to models supporting fields of type from another model.

Will this enable FK support like in Hibernate:
@Entity
public class Task {
    @Id @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "task_id")
    private int id;
    @ManyToOne
    @JoinColumn(name = "task_status_id")
    TaskStatus status;
}

In f-orm-m8 I proposed to signal Fks at the @DataColumn annotation level in the CompositeConstraint list.
Annotations could be placed on fields of complex types, which in turn will have a representation in the database in dedicated tables. As well, the annotations could be placed on the fields that represent the primary key combination of the entity being referenced.
At the level of implementation, which is the most appropriate approach, should be discussed. If the inheritance chain is an aciclic graph (i.e. a tree), the load seems feasible. The problem arises when we encounter cyclic dependencies, involving a lot of tests, validations and eternal questioning who was the first "egg or chicken."
As you mentioned well, an extra set of annotations is likely to be needed.

Sorry for the late response. I am a bit confused when you talk about the database as an cyclic graph. From my understanding, an ORM will only provide "one hop", using foreign keys to connect 2 tables.

Looking to the generation workflow, the database is on the output side of stream. The input is a collection of models. The engine must parse each field of a model and extract the needed information to write a proper proxy and the database provider methods (table creation, entity CRUD).
When I am speaking of dependency chain, I am thinking to the model fields that are of another model type. The FK come in to scene when we need to implement one-to-many and many-to-many relationships. For example, a trivial one-to-many case, seems easy to handle:
class ModelA {
  int id;
  ModelB sampleField;
}

class ModelB {
  int id;
}

The troubles are coming to scene when we try to inspect the following case, which involve a cyclic graph:
class ParentModel {
  int id;
  ChildModel childField;
}

class ChildModel {
  int id;
  ParentModel parent;
}

And the list may continue....

I have the need to store products and allergens. Is this possible using the ORM?
So one product may contain many allergens.
Here's what my models look like:

import 'package:f_orm_m8/f_orm_m8.dart';

@DataTable("product_db_models")
class Product implements DbEntity {
  @DataColumn("id", metadataLevel: ColumnMetadata.primaryKey)
  @override
  int id;
  @DataColumn("name")
  final String name;
  @DataColumn("description")
  final String description;
  @DataColumn("price")
  final double price;
  @DataColumn("imagePath")
  final String imagePath;
  @DataColumn("hasOptions")
  final bool hasOptions;

  @DataColumn("allergens")
  List<int> productAllergens;

  Product(this.name, this.description, this.price, this.imagePath,
      this.hasOptions, this.productAllergens, this.id);
}

import 'package:f_orm_m8/annotation/column_metadata.dart';
import 'package:f_orm_m8/annotation/data_column.dart';
import 'package:f_orm_m8/f_orm_m8.dart';

@DataTable("product_db_allergens")
class Allergen implements DbEntity {
  @DataColumn("id",
      metadataLevel: ColumnMetadata.primaryKey | ColumnMetadata.autoIncrement)
  @override
  int id;

  @DataColumn("name")
  String name;

  Allergen(this.name);
}

When I try to implement a list in this framework I get:
Error: The type List of Product.productAllergens is not implemented. Remove it from the model.

  @DataColumn("allergens")
  List<int> productAllergens;

Change the type from int to Allergen
  @DataColumn("allergens")
  List<Allergen> productAllergens;

Sorry yeah I tried that too but I had the same problem
On Sun, 7 Jun 2020, 10:48 Stefan Lobbenmeier<EMAIL_ADDRESS>wrote:

@DataColumn("allergens")
List productAllergens;
Change the type from int to Allergen
@DataColumn("allergens")
List productAllergens;
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/matei-tm/f-orm-m8-sqlite/issues/96#issuecomment-640187464,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AA6XBOOFYPR374UXF4GIX6LRVNPAHANCNFSM4HNMSZGA
.

Oh my bad it’s been a while since I looked into this project. I guess this ORM leaves relationships to implement for the user. (This was also what my original question  was about).
In your case you have a n:m relationship so you will need an additional table “ProductAllergens” with the fields Product and Allergen.

Ah I see, I'd need a Tuple / Mapping class to represent the table.

Any chance you could give an example of what the join table might look like? Will it use ID's does it need certain decorators?

class ProductAllergen {

  @DataColumn("id", metadataLevel: ColumnMetadata.primaryKey)
 int productId;

  @DataColumn("id", metadataLevel: ColumnMetadata.primaryKey)
int allergenId;

Future<List<Allergen>> getAllergens(int productid) async {
    var dbClient = await db;
    List<Map> result = await dbClient.query(theProductAllergenTableHandler,
        columns: theProductAllergenColumns, where: '1 AND productid = ?', whereArgs: [productid]);

    if (result.length > 0) {
      return ProductAllergenProxy.fromMap(result.first).map(pa -> Allergen.getById(pa.allergenId);
    }

    return null;
  }

}

Something along these lines. I am at my phone right now sorry for all the syntax errors :)


CC77710: Adding description of default model validation

Hello, @tdykstra,
This proposed file change comes from https://github.com/aspnet/Docs.zh-cn/pull/82.
Description: Added description of default model validation by https://github.com/aspnet/AspNetCore/issues/3485
Could you review this contribution and help to merge if agreed?
Many thanks in advance.

This is not correct. See  #9262


Update in library.player

The variable playersInParty has been updated in Library.player. See https://github.com/tera-toolbox-mods/library/commit/907319e8c65458ceeb868c919f7c6a41820efdb0
Fix is changing playersInParty.includes(gameId) to playersInParty.has(gameId)
Note: Needs to be fixed here as well https://github.com/hsdn/tera-guide/blob/d3d032fcb278fbdb5f7c4ee16d66be8b1eb16f06/guides/3020.js#L155

Forgot to link this https://github.com/hsdn/tera-guide-core/blob/60ebd9eb75d05cf5f3ef7ad1787e83931ce42be4/lib/core/events/hooks/S_ABNORMALITY_BEGIN.js#L23

Hi, updated https://github.com/hsdn/tera-guide-core/commit/d8afecf9651276c47513bcb4de9b2f27855f3647. Thank you for notice.


Allow access to http_client thread so it can be waited on

What is the use case?

What is the use case?

Something as simple as a client that simply wants to gather messages
client = MessageBus::HTTPClient.new("http://a.ca")
client.subscribe('/bob") { do_something }
The next line is the issue - the client is running on a background thread so I need to do something to keep the app alive. I can sleep, loop, or with this PR simply thread#join on the client thread.
The StopError exception also lets the client properly exit the thread as well if a message to exit came through. Something like
client.subscribe("/exit") { client.stop } would immediately exit the thread via the exception and shut down the connection. I'm sure I could just exit the app but if the app wanted a cleaner way to shut things down (i.e. it does other work after getting the exit message) I think the exception provides a method to accomplish that.

Do we want to simplify the API a bit to avoid leaking out implementation details?
Maybe simply allow client.wait which can call the Thread.join.
Then if our implementation ever changes we don't need to be tied to this very specific detail?

Sorry, closing this as I don't want to leak implementation details out of the class, thread is a detail. Instead a PR to add .wait sound A-OK to me and that can do the thread.join .


Chip tool server crash on raspi4 when doing connect using python chip-device-ctrl

When trying to connect to the chip device on raspi4
Stack trace from the python device controller
python3 chip-device-ctrl
Chip Device Controller Shell
chip-device-ctrl > help
Available commands (type help  for more information):
ble-adapter-print   ble-disconnect    close
ble-adapter-select  ble-scan          connect
ble-connect         ble-scan-connect  set-pairing-wifi-credential
ble-debug-log       btp-connect
chip-device-ctrl > ble-scan-connect CHIP-2976
2020-10-30 11:07:01,030 ChipBLEMgr   INFO     BLE is ready!
2020-10-30 11:07:01,432 ChipBLEMgr   INFO     adding to scan list:
2020-10-30 11:07:01,432 ChipBLEMgr   INFO
2020-10-30 11:07:01,432 ChipBLEMgr   INFO     Name =    None
2020-10-30 11:07:01,432 ChipBLEMgr   INFO     ID =      BF518E80-E89D-47FF-A645-4B2D1D9E27D2
2020-10-30 11:07:01,432 ChipBLEMgr   INFO     RSSI =    -46
2020-10-30 11:07:01,433 ChipBLEMgr   INFO     ADV data: {
kCBAdvDataChannel = 37;
kCBAdvDataIsConnectable = 1;
kCBAdvDataServiceData =     {
FEAF = {length = 3, bytes = 0x000f00};
};
}
2020-10-30 11:07:01,433 ChipBLEMgr   INFO
2020-10-30 11:07:05,655 ChipBLEMgr   INFO     adding to scan list:
2020-10-30 11:07:05,655 ChipBLEMgr   INFO
2020-10-30 11:07:05,655 ChipBLEMgr   INFO     Name =    None
2020-10-30 11:07:05,655 ChipBLEMgr   INFO     ID =      C721EBDD-B7EE-4AE0-949B-49481DC4CB2C
2020-10-30 11:07:05,655 ChipBLEMgr   INFO     RSSI =    -56
2020-10-30 11:07:05,656 ChipBLEMgr   INFO     ADV data: {
kCBAdvDataChannel = 37;
kCBAdvDataIsConnectable = 1;
kCBAdvDataServiceData =     {
FEAF = {length = 17, bytes = 0x1001010101000100010000000000000000};
};
kCBAdvDataServiceUUIDs =     (
FEAF
);
}
2020-10-30 11:07:05,656 ChipBLEMgr   INFO
2020-10-30 11:07:05,656 ChipBLEMgr   INFO     scanning stopped
2020-10-30 11:07:05,656 ChipBLEMgr   INFO     trying to connect to CHIP-2976
2020-10-30 11:07:08,453 ChipBLEMgr   INFO     Discovering services
2020-10-30 11:07:08,455 ChipBLEMgr   INFO     Discovering services
2020-10-30 11:07:08,615 ChipBLEMgr   INFO     connect success
chip-device-ctrl > set-pairing-wifi-credential testap testtest
WiFi credential set
chip-device-ctrl > connect 12345678
CHIP: [BLE] subscribe complete, ep = 0x114690c88
CHIP: [BLE] connect handshake timed out, closing ep 0x114690c88
CHIP: [BLE] Auto-closing end point's BLE connection.
2020-10-30 11:07:47,426 ChipBLEMgr   INFO     BLE disconnected, error = None
Here is stack trace from the raspi , chip tool server...
<suggested fix, suggested enhancement>
CHIP:DL: SET service data to {'0xFEAF': <[byte 0x10, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]>}
CHIP:DL: HandlePlatformSpecificBLEEvent , 16388
CHIP:DL: CHIPoBLE advertising config complete
CHIP:DL: RegisterAdvertisement complete
CHIP:DL: HandlePlatformSpecificBLEEvent , 16389
[Thread 0xfffff56cefc0 (LWP 2440211) exited]
Thread 4 "chip-tool-serve" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0xfffff5ecffc0 (LWP 2440210)]
0x0000fffff7b752b0 in g_str_hash () from /lib/aarch64-linux-gnu/libglib-2.0.so.0
(gdb) bt
#0  0x0000fffff7b752b0 in g_str_hash () at /lib/aarch64-linux-gnu/libglib-2.0.so.0
#1  0x0000fffff7b73a4c in g_hash_table_lookup () at /lib/aarch64-linux-gnu/libglib-2.0.so.0
#2  0x0000aaaaaaae634c in chip::DeviceLayer::Internal::GetBluezConnectionViaDevice(chip::DeviceLayer::Internal::BluezEndpoint*)
(apEndpoint=0xaaaaaacd5f00) at ../../third_party/connectedhomeip/src/platform/Linux/CHIPBluezHelper.cpp:1115
#3  0x0000aaaaaaae4430 in chip::DeviceLayer::Internal::BluezCharacteristicAcquireWrite(BluezGattCharacteristic1*, GDBusMethodInvocation*, GVariant*, gpointer) (aChar=0xffffe4003b50, aInvocation=0xffffe802c480, aOptions=0xffffe8027520, apEndpoint=0xaaaaaacd5f00)
at ../../third_party/connectedhomeip/src/platform/Linux/CHIPBluezHelper.cpp:407
#4  0x0000fffff734d148 in  () at /lib/aarch64-linux-gnu/libffi.so.8
#5  0x0000fffff734c748 in  () at /lib/aarch64-linux-gnu/libffi.so.8
#6  0x0000fffff7c8da50 in g_cclosure_marshal_generic () at /lib/aarch64-linux-gnu/libgobject-2.0.so.0
#7  0x0000fffff7c8d058 in g_closure_invoke () at /lib/aarch64-linux-gnu/libgobject-2.0.so.0
#8  0x0000fffff7ca1c74 in  () at /lib/aarch64-linux-gnu/libgobject-2.0.so.0
#9  0x0000aaaaaab6cfec in _bluez_gatt_characteristic1_skeleton_handle_method_call
(connection=0xaaaaaacc3040, sender=0xffffe802b580 ":1.5", object_path=0xffffe802d210 "/chipoble/3c0d/service/c1", interface_name=0xffffe802c090 "org.bluez.GattCharacteristic1", method_name=0xffffe802c070 "AcquireWrite", parameters=0xffffe8004af0, invocation=0xffffe802c480, user_data=0xffffe4003b50) at gen/platform/Linux/dbus/bluez/DbusBluez.c:12258
#10 0x0000fffff7e210e8 in  () at /lib/aarch64-linux-gnu/libgio-2.0.so.0
#11 0x0000fffff7e05704 in  () at /lib/aarch64-linux-gnu/libgio-2.0.so.0
#12 0x0000fffff7b879f0 in g_main_context_dispatch () at /lib/aarch64-linux-gnu/libglib-2.0.so.0
#13 0x0000fffff7b87d98 in  () at /lib/aarch64-linux-gnu/libglib-2.0.so.0
#14 0x0000fffff7b880f0 in g_main_loop_run () at /lib/aarch64-linux-gnu/libglib-2.0.so.0
#15 0x0000aaaaaaaec528 in chip::DeviceLayer::GDBus_Thread() ()
at ../../third_party/connectedhomeip/src/platform/Linux/PlatformManagerImpl.cpp:45
#16 0x0000aaaaaaaee9a4 in std::__invoke_impl<void, void ()()>(std::__invoke_other, void (&&)())
(__f=@0xffffe8006cd8: 0xaaaaaaaec508 chip::DeviceLayer::GDBus_Thread()) at /usr/include/c++/10/bits/invoke.h:60
#17 0x0000aaaaaaaee930 in std::__invoke<void ()()>(void (&&)()) (__fn=@0xffffe8006cd8: 0xaaaaaaaec508 chip::DeviceLayer::GDBus_Thread())
at /usr/include/c++/10/bits/invoke.h:95
#18 0x0000aaaaaaaee8cc in std::thread::_Invoker<std::tuple<void ()()> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) (this=0xffffe8006cd8)
at /usr/include/c++/10/thread:264
#19 0x0000aaaaaaaee8a0 in std::thread::_Invoker<std::tuple<void ()()> >::operator()() (this=0xffffe8006cd8)
at /usr/include/c++/10/thread:271
#20 0x0000aaaaaaaee880 in std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)()> > >::_M_run() (this=0xffffe8006cd0)
at /usr/include/c++/10/thread:215
--Type  for more, q to quit, c to continue without paging--
#21 0x0000fffff7787e1c in  () at /lib/aarch64-linux-gnu/libstdc++.so.6
#22 0x0000fffff7f8ef74 in start_thread (arg=0x0) at pthread_create.c:463
#23 0x0000fffff76183dc in thread_start () at ../sysdeps/unix/sysv/linux/aarch64/clone.S:78CHIP:DL: SET service data to {'0xFEAF': <[byte 0x10, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]>}
CHIP:DL: HandlePlatformSpecificBLEEvent , 16388
CHIP:DL: CHIPoBLE advertising config complete
CHIP:DL: RegisterAdvertisement complete
CHIP:DL: HandlePlatformSpecificBLEEvent , 16389
[Thread 0xfffff56cefc0 (LWP 2440211) exited]
Thread 4 "chip-tool-serve" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0xfffff5ecffc0 (LWP 2440210)]
0x0000fffff7b752b0 in g_str_hash () from /lib/aarch64-linux-gnu/libglib-2.0.so.0
(gdb) bt
#0  0x0000fffff7b752b0 in g_str_hash () at /lib/aarch64-linux-gnu/libglib-2.0.so.0
#1  0x0000fffff7b73a4c in g_hash_table_lookup () at /lib/aarch64-linux-gnu/libglib-2.0.so.0
#2  0x0000aaaaaaae634c in chip::DeviceLayer::Internal::GetBluezConnectionViaDevice(chip::DeviceLayer::Internal::BluezEndpoint*)
(apEndpoint=0xaaaaaacd5f00) at ../../third_party/connectedhomeip/src/platform/Linux/CHIPBluezHelper.cpp:1115
#3  0x0000aaaaaaae4430 in chip::DeviceLayer::Internal::BluezCharacteristicAcquireWrite(BluezGattCharacteristic1*, GDBusMethodInvocation*, GVariant*, gpointer) (aChar=0xffffe4003b50, aInvocation=0xffffe802c480, aOptions=0xffffe8027520, apEndpoint=0xaaaaaacd5f00)
at ../../third_party/connectedhomeip/src/platform/Linux/CHIPBluezHelper.cpp:407
#4  0x0000fffff734d148 in  () at /lib/aarch64-linux-gnu/libffi.so.8
#5  0x0000fffff734c748 in  () at /lib/aarch64-linux-gnu/libffi.so.8
#6  0x0000fffff7c8da50 in g_cclosure_marshal_generic () at /lib/aarch64-linux-gnu/libgobject-2.0.so.0
#7  0x0000fffff7c8d058 in g_closure_invoke () at /lib/aarch64-linux-gnu/libgobject-2.0.so.0
#8  0x0000fffff7ca1c74 in  () at /lib/aarch64-linux-gnu/libgobject-2.0.so.0
#9  0x0000aaaaaab6cfec in _bluez_gatt_characteristic1_skeleton_handle_method_call
(connection=0xaaaaaacc3040, sender=0xffffe802b580 ":1.5", object_path=0xffffe802d210 "/chipoble/3c0d/service/c1", interface_name=0xffffe802c090 "org.bluez.GattCharacteristic1", method_name=0xffffe802c070 "AcquireWrite", parameters=0xffffe8004af0, invocation=0xffffe802c480, user_data=0xffffe4003b50) at gen/platform/Linux/dbus/bluez/DbusBluez.c:12258
#10 0x0000fffff7e210e8 in  () at /lib/aarch64-linux-gnu/libgio-2.0.so.0
#11 0x0000fffff7e05704 in  () at /lib/aarch64-linux-gnu/libgio-2.0.so.0
#12 0x0000fffff7b879f0 in g_main_context_dispatch () at /lib/aarch64-linux-gnu/libglib-2.0.so.0
#13 0x0000fffff7b87d98 in  () at /lib/aarch64-linux-gnu/libglib-2.0.so.0
#14 0x0000fffff7b880f0 in g_main_loop_run () at /lib/aarch64-linux-gnu/libglib-2.0.so.0
#15 0x0000aaaaaaaec528 in chip::DeviceLayer::GDBus_Thread() ()
at ../../third_party/connectedhomeip/src/platform/Linux/PlatformManagerImpl.cpp:45
#16 0x0000aaaaaaaee9a4 in std::__invoke_impl<void, void ()()>(std::__invoke_other, void (&&)())
(__f=@0xffffe8006cd8: 0xaaaaaaaec508 chip::DeviceLayer::GDBus_Thread()) at /usr/include/c++/10/bits/invoke.h:60
#17 0x0000aaaaaaaee930 in std::__invoke<void ()()>(void (&&)()) (__fn=@0xffffe8006cd8: 0xaaaaaaaec508 chip::DeviceLayer::GDBus_Thread())
at /usr/include/c++/10/bits/invoke.h:95
#18 0x0000aaaaaaaee8cc in std::thread::_Invoker<std::tuple<void ()()> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) (this=0xffffe8006cd8)
at /usr/include/c++/10/thread:264
#19 0x0000aaaaaaaee8a0 in std::thread::_Invoker<std::tuple<void ()()> >::operator()() (this=0xffffe8006cd8)
at /usr/include/c++/10/thread:271
#20 0x0000aaaaaaaee880 in std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)()> > >::_M_run() (this=0xffffe8006cd0)
at /usr/include/c++/10/thread:215
--Type  for more, q to quit, c to continue without paging--
#21 0x0000fffff7787e1c in  () at /lib/aarch64-linux-gnu/libstdc++.so.6
#22 0x0000fffff7f8ef74 in start_thread (arg=0x0) at pthread_create.c:463
#23 0x0000fffff76183dc in thread_start () at ../sysdeps/unix/sysv/linux/aarch64/clone.S:78

The same crashes happens after scanning QR code with the Android app.

Temporary workaround for this issue when using python device controller:
ble-scan-connect xxxxx
ble-disconnect
ble-scan-connect xxxxx

(After connect, run ble-disconnect and connect it again)

The cause of this issue is "Connect" property change event is not fired by bluez.


Home assistant stream not using Frigate live config settings

Version of the custom_component
Frigate version: 0.10.1
Home Assistant Core 2022.5.4
Configuration
      "live": {
        "height": 720,
        "quality": 31
      },

Describe the bug
It seems like the camera entity in home assistant is not using the live config settings. Or is that by design? I set the live settings so I could use it in home assistant while I'm away from home. I cannot set the resolution on the camera. The home assistant stream is using the original 1080p stream like the entity is just using the rtsp stream instead from Frigate.
Frigate

Home assistant

We need more information from the config. The integration uses the rtmp stream from frigate which doesn't have a height adjustment.
# Optional: RTMP configuration
# NOTE: Can be overridden at the camera level
rtmp:
  # Optional: Enable the RTMP stream (default: True)
  enabled: True

the live you are referencing seems to be the one for the frigate front end web UI

@NickM-27 Thanks for the quick reply. This may be the wrong place to ask, on frigates doc, it looks like you can override the output args for rtmp, but I am not sure what the options are. Are you aware of any? If not, I can close this issue out as its now more related to Frigate configuration.
  # Optional: global output args
  output_args:
    # Optional: output args for detect streams (default: shown below)
    detect: -f rawvideo -pix_fmt yuv420p
    # Optional: output args for record streams (default: shown below)
    record: -f segment -segment_time 10 -segment_format mp4 -reset_timestamps 1 -strftime 1 -c copy -an
    # Optional: output args for rtmp streams (default: shown below)
    rtmp: -c copy -f flv

I'm not sure that the rtmp allows for changing the size since I think it is set to basically be a copy of what comes in, I'd have to check if others have asked that in the past.
But yeah that would be a question to put into the other repo.

Thanks for the help, I will close out this issue then and look over in that repo.

@NickM-27  just wanted to give you an update.
If anyone has the same issue. I was able to fix this by setting the output_args for rtmp for my device and discovered these settings are general ffmpeg parameters. I used ffprobe to determine what stream types my camera was capable of.
      output_args:
        detect: -f rawvideo -pix_fmt yuv420p
        record: -f segment -segment_time 60 -segment_format mp4 -reset_timestamps 1 -strftime 1 -c copy -an
        rtmp: -c copy -f flv -pix_fmt yuv420p

Then using the Frigate frontend hass card, i could use the frigate-jsmpeg provider for streaming on mobile data it works pretty nicely I will say.
https://github.com/dermotduffy/frigate-hass-card#available-live-providers