Dear Community User! We have started the migration process.
This community is now in READ ONLY mode.
Read more: Important information on the platform change.

cancel
Showing results for 
Search instead for 
Did you mean: 
SOLVED

Issue with AppArmor denial on unix socket binding in third-party snap application

Issue with AppArmor denial on unix socket binding in third-party snap application

CtrlXplorer
Established Member

Hello Everyone,

I'm reaching out to seek assistance with an issue I'm facing regarding socket binding in a snap application, along with an AppArmor denial error.

Problem Description:
I've developed a C++ program that acts as a Unix socket server, serving as a middleware between the licensing manager API and another application. The program creates a directory and listens for incoming connections via a Unix domain socket. When I run the C++ executable locally on my Ubuntu 20.04 development machine, the socket is bound successfully, and the server listens for incoming connections without any issues.

However, after building a snap of the program and installing it on my CtrlX Core Virtual device (version 1.20.12), I encounter the following errors (Diagnostics ->Logbook):

  • Error on binding socket
  • AVC apparmor="DENIED" operation="bind" profile="snap.licensing.licensing" pid=10550 comm="check-license" family="unix" sock_type="stream" protocol=0 requested_mask="bind" denied_mask="bind" addr=none

 

Additional Information:

Build Environment: Ubuntu 20.04
Snap Base: core20
CtrlX Core Virtual Version: 1.20.12
CtrlX Works Version: 1.20.5

Here is my snapcraft.yaml file:

 

name: licensing
version: "0.0.1"
grade: stable
base: core20
confinement: strict

apps:
  licensing:
    command: check-license
    plugs:
      - network
      - network-bind
      - content
      - system-files
    daemon: simple
    passthrough:
      restart-condition: on-failure
      restart-delay: 10s

parts:
  licensing:
    plugin: dump
    source: ./generated/build
    stage-packages:
    - libasn1-8-heimdal
    - libbrotli1
    - libcurl4
    - libgssapi3-heimdal
    - libhcrypto4-heimdal
    - libheimbase1-heimdal
    - libheimntlm0-heimdal
    - libhx509-5-heimdal
    - libkrb5-26-heimdal
    - libldap-2.4-2
    - libnghttp2-14
    - libpsl5
    - libroken18-heimdal
    - librtmp1
    - libsasl2-2
    - libssh-4
    - libwind0-heimdal  

 

 


And also my main.cpp:

 

#include <iostream>
#include <fstream>
#include <filesystem>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include "helper/helper.h"
#include "third_party/nlohmann/json.hpp"
#include "licensing-service/licenseClient.h"
#include "constants.h"

// Use the nlohmann namespace for JSON parsing 
using json = nlohmann::json;

// Use the std namespace for standard C++ functions
using namespace std;

int main()
{
    Helper installer; // Create an instance of the class that contains helper functions for the installer
    LicenseClient licenseClient; // Create an instance of the class that contains functions to access the License Manager API

    const string snapCommonPath = installer.getEnvVar("SNAP_COMMON");

    string licensingSocketPath = snapCommonPath + "/sockets";

    const char* socket_path = (licensingSocketPath + "/licensing.sock").c_str();

    const int nIncomingConnections = 5;
    const int backlog = 5; // Maximum number of pending connections in the queue

    bool doDirectoriesExcist = filesystem::exists(licensingSocketPath);

    if (!doDirectoriesExcist)
    {
        // Create the directories
        filesystem::create_directories(licensingSocketPath);
        cout << "Directories created successfully" << endl;
    }

    // Create socket
    //create server side
	int s = 0;
	int s2 = 0;
	struct sockaddr_un local, remote;
	int len = 0;

	s = socket(AF_UNIX, SOCK_STREAM, 0);
	if( -1 == s )
	{
		printf("Error on socket() call \n");
		return 1;
	}

	local.sun_family = AF_UNIX;
	strcpy( local.sun_path, socket_path );
	unlink(local.sun_path);
	len = strlen(local.sun_path) + sizeof(local.sun_family);
	if( bind(s, (struct sockaddr*)&local, len) != 0)
	{
		printf("Error on binding socket \n");
		return 1;
	}

	if( listen(s, nIncomingConnections) != 0 )
	{
		printf("Error on listen call \n");
	}

	bool bWaiting = true;
	while (bWaiting)
	{
		unsigned int sock_len = 0;
		printf("Waiting for connection.... \n");
		if( (s2 = accept(s, (struct sockaddr*)&remote, &sock_len)) == -1 )
		{
			printf("Error on accept() call \n");
			return 1;
		}

		printf("Server connected \n");

		int data_recv = 0;
		char recv_buf[100];
		char send_buf[200];
		do{
			memset(recv_buf, 0, 100*sizeof(char));
			memset(send_buf, 0, 200*sizeof(char));
			data_recv = recv(s2, recv_buf, 100, 0);
			if(data_recv > 0)
			{
				printf("Data received: %d : %s \n", data_recv, recv_buf);
				strcpy(send_buf, "Got message: ");
				strcat(send_buf, recv_buf);

				if(strstr(recv_buf, "quit")!=0)
				{
					printf("Exit command received -> quitting \n");
					bWaiting = false;
					break;
				}

				if( send(s2, send_buf, strlen(send_buf)*sizeof(char), 0) == -1 )
				{
					printf("Error on send() call \n");
				}
			}
			else
			{
				printf("Error on recv() call \n");
			}
		}while(data_recv > 0);

		close(s2);
	}

    return 0;
}

 



Your assistance and insights on this matter would be greatly appreciated. Please let me know if you require any further information or if there are any specific details I should provide.

Thank you in advance!

2 REPLIES 2

MauroRiboniMX
Contributor
@CtrlXplorer I am giving a look to understand what could be the problem here! Seem really strange a connected with how you are creating that socket.

Have you tried to install the app as --devmode? What happens?

Hello @MauroRiboniMX ,

Thank you all for your insights regarding the issue.

After further investigation and experimentation, I tried installing the snap as devmode in Ubuntu 20.04 and discovered that indeed there is an issue with the socket creation. It seems that certain permissions or configurations are missing within the snap environment, causing these problems to occur.

In light of these difficulties and to avoid further complications with sockets, I have decided to change my approach for Inter-Process Communication (IPC). Instead of utilizing sockets, I will be transitioning to using shared memory.

Shared memory offers a robust and efficient means of communication between processes, and it circumvents some of the challenges encountered with socket permissions and configurations within the snap environment.

Once again, I appreciate all the support!


P.S. I will be closing the ticket now.

Icon--AD-black-48x48Icon--address-consumer-data-black-48x48Icon--appointment-black-48x48Icon--back-left-black-48x48Icon--calendar-black-48x48Icon--center-alignedIcon--Checkbox-checkIcon--clock-black-48x48Icon--close-black-48x48Icon--compare-black-48x48Icon--confirmation-black-48x48Icon--dealer-details-black-48x48Icon--delete-black-48x48Icon--delivery-black-48x48Icon--down-black-48x48Icon--download-black-48x48Ic-OverlayAlertIcon--externallink-black-48x48Icon-Filledforward-right_adjustedIcon--grid-view-black-48x48IC_gd_Check-Circle170821_Icons_Community170823_Bosch_Icons170823_Bosch_Icons170821_Icons_CommunityIC-logout170821_Icons_Community170825_Bosch_Icons170821_Icons_CommunityIC-shopping-cart2170821_Icons_CommunityIC-upIC_UserIcon--imageIcon--info-i-black-48x48Icon--left-alignedIcon--Less-minimize-black-48x48Icon-FilledIcon--List-Check-grennIcon--List-Check-blackIcon--List-Cross-blackIcon--list-view-mobile-black-48x48Icon--list-view-black-48x48Icon--More-Maximize-black-48x48Icon--my-product-black-48x48Icon--newsletter-black-48x48Icon--payment-black-48x48Icon--print-black-48x48Icon--promotion-black-48x48Icon--registration-black-48x48Icon--Reset-black-48x48Icon--right-alignedshare-circle1Icon--share-black-48x48Icon--shopping-bag-black-48x48Icon-shopping-cartIcon--start-play-black-48x48Icon--store-locator-black-48x48Ic-OverlayAlertIcon--summary-black-48x48tumblrIcon-FilledvineIc-OverlayAlertwhishlist